| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109 |
- import { ReactNode } from 'react'
- import { Link, useLocation } from '@tanstack/react-router'
- import { ChevronRight } from 'lucide-react'
- import {
- Collapsible,
- CollapsibleContent,
- CollapsibleTrigger,
- } from '@/components/ui/collapsible'
- import {
- SidebarGroup,
- SidebarGroupLabel,
- SidebarMenu,
- SidebarMenuButton,
- SidebarMenuItem,
- SidebarMenuSub,
- SidebarMenuSubButton,
- SidebarMenuSubItem,
- useSidebar,
- } from '@/components/ui/sidebar'
- import { Badge } from '../ui/badge'
- import { NavItem, type NavGroup } from './types'
- export function NavGroup({ title, items }: NavGroup) {
- const { setOpenMobile } = useSidebar()
- const href = useLocation({ select: (location) => location.href })
- return (
- <SidebarGroup>
- <SidebarGroupLabel>{title}</SidebarGroupLabel>
- <SidebarMenu>
- {items.map((item) => {
- if (!item.items) {
- return (
- <SidebarMenuItem key={item.title}>
- <SidebarMenuButton
- asChild
- isActive={checkIsActive(href, item)}
- tooltip={item.title}
- >
- <Link to={item.url} onClick={() => setOpenMobile(false)}>
- {item.icon && <item.icon />}
- <span>{item.title}</span>
- {item.badge && <NavBadge>{item.badge}</NavBadge>}
- </Link>
- </SidebarMenuButton>
- </SidebarMenuItem>
- )
- }
- return (
- <Collapsible
- key={item.title}
- asChild
- defaultOpen={checkIsActive(href, item, true)}
- className='group/collapsible'
- >
- <SidebarMenuItem>
- <CollapsibleTrigger asChild>
- <SidebarMenuButton tooltip={item.title}>
- {item.icon && <item.icon />}
- <span>{item.title}</span>
- {item.badge && <NavBadge>{item.badge}</NavBadge>}
- <ChevronRight className='ml-auto transition-transform duration-200 group-data-[state=open]/collapsible:rotate-90' />
- </SidebarMenuButton>
- </CollapsibleTrigger>
- <CollapsibleContent className='CollapsibleContent'>
- <SidebarMenuSub>
- {item.items.map((subItem) => (
- <SidebarMenuSubItem key={subItem.title}>
- <SidebarMenuSubButton
- asChild
- isActive={checkIsActive(href, subItem)}
- >
- <Link
- to={subItem.url}
- onClick={() => setOpenMobile(false)}
- >
- {subItem.icon && <subItem.icon />}
- <span>{subItem.title}</span>
- {subItem.badge && (
- <NavBadge>{subItem.badge}</NavBadge>
- )}
- </Link>
- </SidebarMenuSubButton>
- </SidebarMenuSubItem>
- ))}
- </SidebarMenuSub>
- </CollapsibleContent>
- </SidebarMenuItem>
- </Collapsible>
- )
- })}
- </SidebarMenu>
- </SidebarGroup>
- )
- }
- const NavBadge = ({ children }: { children: ReactNode }) => (
- <Badge className='text-xs rounded-full px-1 py-0'>{children}</Badge>
- )
- function checkIsActive(href: string, item: NavItem, mainNav = false) {
- return (
- href === item.url || // /endpint?search=param
- href.split('?')[0] === item.url || // endpoint
- !!item?.items?.filter((i) => i.url === href).length || // if child nav is active
- (mainNav &&
- href.split('/')[1] !== '' &&
- href.split('/')[1] === item?.url?.split('/')[1])
- )
- }
|