import { Fragment, useEffect, useRef, useState } from "react"; /** * Improved Breadcrumbs helper component * - Renders a pill-style path with chevrons * - Collapses middle items when path is long and exposes them via an ellipsis dropdown * - Clickable items, accessible, responsive truncation */ export type FolderMeta = { id: number | null; name: string | null; parentId: number | null; }; export function Breadcrumbs({ path, onNavigate, }: { path: FolderMeta[]; onNavigate: (id: number | null) => void; }) { const [openEllipsis, setOpenEllipsis] = useState(false); const dropdownRef = useRef(null); // close dropdown on outside click useEffect(() => { function onDocClick(e: MouseEvent) { if (!dropdownRef.current) return; if (!dropdownRef.current.contains(e.target as Node)) { setOpenEllipsis(false); } } if (openEllipsis) { document.addEventListener("mousedown", onDocClick); } return () => document.removeEventListener("mousedown", onDocClick); }, [openEllipsis]); // Render strategy: if path.length <= 4 show all; else show: first, ellipsis, last 2 const showAll = path.length <= 4; const first = path[0]; const lastTwo = path.slice(Math.max(0, path.length - 2)); const middle = path.slice(1, Math.max(1, path.length - 2)); // utility classes const inactiveChip = "inline-flex items-center gap-2 px-3 py-1 rounded-full text-sm truncate max-w-[220px] bg-muted hover:bg-muted/80 text-muted-foreground"; const activeChip = "inline-flex items-center gap-2 px-3 py-1 rounded-full text-sm truncate max-w-[220px] bg-primary/10 text-primary ring-1 ring-primary/20"; // render a chip with optional active flag function Chip({ id, name, active, }: { id: number | null; name: string | null; active?: boolean; }) { return ( ); } // small slash separator (visible between chips) const Slash = () =>
  • /
  • ; return ( // Card-like background for the entire breadcrumb strip ); }