SurfSense/surfsense_web/components/sidebar/nav-main.tsx

86 lines
2.5 KiB
TypeScript
Raw Normal View History

2025-07-27 10:05:37 -07:00
"use client";
2025-04-07 23:47:06 -07:00
2025-07-27 10:05:37 -07:00
import { ChevronRight, type LucideIcon } from "lucide-react";
2025-08-02 21:20:36 -07:00
import { useMemo } from "react";
2025-04-07 23:47:06 -07:00
2025-07-27 10:05:37 -07:00
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "@/components/ui/collapsible";
2025-04-07 23:47:06 -07:00
import {
2025-07-27 10:05:37 -07:00
SidebarGroup,
SidebarGroupLabel,
SidebarMenu,
SidebarMenuAction,
SidebarMenuButton,
SidebarMenuItem,
SidebarMenuSub,
SidebarMenuSubButton,
SidebarMenuSubItem,
} from "@/components/ui/sidebar";
2025-04-07 23:47:06 -07:00
2025-08-02 21:20:36 -07:00
interface NavItem {
title: string;
url: string;
icon: LucideIcon;
isActive?: boolean;
items?: {
2025-07-27 10:05:37 -07:00
title: string;
url: string;
}[];
2025-08-02 21:20:36 -07:00
}
export function NavMain({ items }: { items: NavItem[] }) {
// Memoize items to prevent unnecessary re-renders
const memoizedItems = useMemo(() => items, [items]);
2025-07-27 10:05:37 -07:00
return (
<SidebarGroup>
<SidebarGroupLabel>Platform</SidebarGroupLabel>
<SidebarMenu>
2025-08-02 21:20:36 -07:00
{memoizedItems.map((item, index) => (
2025-07-27 10:05:37 -07:00
<Collapsible key={`${item.title}-${index}`} asChild defaultOpen={item.isActive}>
<SidebarMenuItem>
2025-08-02 21:20:36 -07:00
<SidebarMenuButton
asChild
tooltip={item.title}
isActive={item.isActive}
aria-label={`${item.title}${item.items?.length ? " with submenu" : ""}`}
>
2025-07-27 10:05:37 -07:00
<a href={item.url}>
<item.icon />
<span>{item.title}</span>
</a>
</SidebarMenuButton>
2025-08-02 21:20:36 -07:00
2025-07-27 10:05:37 -07:00
{item.items?.length ? (
<>
<CollapsibleTrigger asChild>
2025-08-02 21:20:36 -07:00
<SidebarMenuAction
className="data-[state=open]:rotate-90 transition-transform duration-200"
aria-label={`Toggle ${item.title} submenu`}
>
2025-07-27 10:05:37 -07:00
<ChevronRight />
2025-08-02 21:20:36 -07:00
<span className="sr-only">Toggle submenu</span>
2025-07-27 10:05:37 -07:00
</SidebarMenuAction>
</CollapsibleTrigger>
2025-08-02 21:20:36 -07:00
<CollapsibleContent className="data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:slide-out-to-top-2 data-[state=open]:slide-in-from-top-2 duration-200">
2025-07-27 10:05:37 -07:00
<SidebarMenuSub>
{item.items?.map((subItem, subIndex) => (
<SidebarMenuSubItem key={`${subItem.title}-${subIndex}`}>
2025-08-02 21:20:36 -07:00
<SidebarMenuSubButton asChild aria-label={subItem.title}>
2025-07-27 10:05:37 -07:00
<a href={subItem.url}>
<span>{subItem.title}</span>
</a>
</SidebarMenuSubButton>
</SidebarMenuSubItem>
))}
</SidebarMenuSub>
</CollapsibleContent>
</>
) : null}
</SidebarMenuItem>
</Collapsible>
))}
</SidebarMenu>
</SidebarGroup>
);
2025-04-07 23:47:06 -07:00
}