import { type ReactNode, type CSSProperties } from "react"; import { useTranslation } from "react-i18next"; import { ChevronDown, Eye, EyeOff, Pencil } from "lucide-react"; import { CSS } from "@dnd-kit/utilities"; import { useSortableItem } from "./sortableA11y"; import { DragHandle } from "./DragHandle"; import { IconButton } from "./IconButton"; import { OrderButtons } from "./OrderButtons"; import { Pressable } from "./Pressable"; import { SURFACE } from "./surfaces"; // One "island" card inside a SidePanel: a titled glass-card, and — in the panel's edit mode — a drag // handle and an Up / Down pair (reorder) and a hide toggle. Generalized from the feed sidebar's // WidgetCard so all three panels share the same island look and behavior. `collapsible` groups (the default) get a per-group // collapse chevron; non-collapsible groups render as a plain always-open label + control row, and // their title can instead act as a trigger via `onTitleClick` (e.g. feed "Your tags" -> tag manager). export default function PanelGroup({ id, title, editing, collapsible = true, collapsed, hidden, onToggleCollapse, onToggleHidden, onTitleClick, titleActionLabel, order, children, }: { id: string; title: string; editing: boolean; collapsible?: boolean; collapsed: boolean; hidden: boolean; onToggleCollapse: () => void; onToggleHidden: () => void; onTitleClick?: () => void; titleActionLabel?: string; /** Edit mode's non-drag reorder (WCAG 2.5.7): this group's place and how to move it. */ order?: { from: number; count: number; onMove: (to: number) => void }; children: ReactNode; }) { const { t } = useTranslation(); const { attributes, listeners, setNodeRef, transform, transition, isDragging } = useSortableItem({ id, disabled: !editing, }); const style: CSSProperties = { transform: CSS.Transform.toString(transform), transition }; // Non-collapsible groups are always open (outside edit mode); collapsible ones honour `collapsed`. const showBody = !editing && (!collapsible || !collapsed); // A non-collapsible group's title acts as a trigger when one is provided. const titleIsTrigger = !editing && !collapsible && !!onTitleClick; // min-h-6 + touch-target: when the title is a control (a collapse, a trigger) it is a 24 / 44 target. const titleCls = "flex-1 min-w-0 min-h-6 flex items-center gap-1 select-none text-sm uppercase tracking-wide touch-target"; return (
{editing && ( )} {collapsible && !editing ? ( {title} ) : titleIsTrigger ? ( {title} ) : ( {/* In edit mode the name wraps instead of truncating: the grip, the Up / Down pair and the eye leave a long one ("Feltöltés dátuma") too little room on one line. */} {title} )} {editing && order && } {editing ? ( {hidden ? : } ) : ( collapsible && ( ) )}
{showBody &&
{children}
}
); }