"use client"; import { useState, useEffect } from "react"; import Link from "next/link"; import { usePathname } from "next/navigation"; import { ChevronDown, Menu, X } from "lucide-react"; import { cn } from "@/lib/utils"; export type NavLeaf = { href: string; label: string }; export type NavItem = | { kind: "link"; href: string; label: string; icon: React.ReactNode } | { kind: "group"; label: string; icon: React.ReactNode; children: NavLeaf[] }; export function Sidebar({ items }: { items: NavItem[] }) { const pathname = usePathname(); const [mobileOpen, setMobileOpen] = useState(false); // Close drawer on navigation useEffect(() => { setMobileOpen(false); }, [pathname]); // Lock body scroll when drawer is open useEffect(() => { document.body.style.overflow = mobileOpen ? "hidden" : ""; return () => { document.body.style.overflow = ""; }; }, [mobileOpen]); const renderNav = (onNavigate?: () => void) => ( ); return ( <> {/* Desktop: persistent sidebar (hidden on mobile) */} {/* Mobile: hamburger in the top bar triggers a drawer */} {mobileOpen && (
setMobileOpen(false)} /> )} ); } function LeafLink({ href, label, icon, active, onClick, }: { href: string; label: string; icon: React.ReactNode; active: boolean; onClick?: () => void; }) { return ( {icon} {label} ); } function Group({ item, active }: { item: Extract; active: boolean }) { const [open, setOpen] = useState(active); const pathname = usePathname(); return (
{open && (
{item.children.map((child) => { const childActive = pathname === child.href; return ( {child.label} ); })}
)}
); }