| 29 | } |
| 30 | |
| 31 | export function SideNav({ items, setOpen, className }: SideNavProps) { |
| 32 | const user = useUser(); |
| 33 | const location = useLocation(); |
| 34 | const { isOpen } = useSidebar(); |
| 35 | const [openItem, setOpenItem] = useState(''); |
| 36 | const [lastOpenItem, setLastOpenItem] = useState(''); |
| 37 | |
| 38 | useEffect(() => { |
| 39 | if (isOpen) { |
| 40 | setOpenItem(lastOpenItem); |
| 41 | } else { |
| 42 | setLastOpenItem(openItem); |
| 43 | setOpenItem(''); |
| 44 | } |
| 45 | }, [isOpen]); |
| 46 | |
| 47 | return ( |
| 48 | <nav className="dark"> |
| 49 | {items.map((item) => |
| 50 | item.isChidren ? ( |
| 51 | <Accordion |
| 52 | type="single" |
| 53 | collapsible |
| 54 | className="space-y-2" |
| 55 | key={item.title} |
| 56 | value={openItem} |
| 57 | onValueChange={setOpenItem} |
| 58 | > |
| 59 | <AccordionItem value={item.title} className="border-none"> |
| 60 | <AccordionTrigger |
| 61 | className={cn( |
| 62 | buttonVariants({ variant: 'ghost' }), |
| 63 | 'group relative flex h-12 justify-between px-4 py-2 text-base duration-200 hover:bg-muted hover:no-underline', |
| 64 | )} |
| 65 | > |
| 66 | <div> |
| 67 | <item.icon className={cn('h-5 w-5', item.color)} /> |
| 68 | </div> |
| 69 | <div |
| 70 | className={cn( |
| 71 | 'absolute left-12 text-base duration-200 ', |
| 72 | !isOpen && className, |
| 73 | )} |
| 74 | > |
| 75 | {item.title} |
| 76 | </div> |
| 77 | |
| 78 | {isOpen && ( |
| 79 | <ChevronDownIcon className="h-4 w-4 shrink-0 text-muted-foreground transition-transform duration-200" /> |
| 80 | )} |
| 81 | </AccordionTrigger> |
| 82 | <AccordionContent className="mt-2 space-y-4 pb-1"> |
| 83 | {item.children?.map((child) => ( |
| 84 | <a |
| 85 | key={child.title} |
| 86 | href={child.href} |
| 87 | onClick={() => { |
| 88 | if (setOpen) setOpen(false); |