TopLevelRouteItem.tsx66 lines · main
1import Link from 'next/link'
2import { cn, sidebarMenuButtonVariants, SidebarMenuItem } from 'ui'
3
4import { isDirectLinkAtTopLevel } from './useMobileMenuNavigation'
5import type { Route } from '@/components/ui/ui.types'
6
7export interface TopLevelRouteItemProps {
8 route: Route
9 isActive: boolean
10 hasSubmenu: boolean
11 onTopLevelClick: (route: Route) => void
12 onCloseSheet?: () => void
13}
14
15export function TopLevelRouteItem({
16 route,
17 isActive,
18 hasSubmenu,
19 onTopLevelClick,
20 onCloseSheet,
21}: TopLevelRouteItemProps) {
22 const hasItems = hasSubmenu && !isDirectLinkAtTopLevel(route)
23 const content = (
24 <>
25 {route.icon && (
26 <span className="flex size-5 shrink-0 items-center justify-center [&>svg]:size-5 [&>svg]:shrink-0">
27 {route.icon}
28 </span>
29 )}
30 <span className="truncate">{route.label}</span>
31 </>
32 )
33 const menuButtonClass = cn(
34 sidebarMenuButtonVariants({ size: 'default', hasIcon: !!route.icon }),
35 route.disabled && 'opacity-50 pointer-events-none'
36 )
37
38 return (
39 <SidebarMenuItem key={route.key}>
40 {hasItems ? (
41 <button
42 type="button"
43 data-active={isActive}
44 onClick={() => onTopLevelClick(route)}
45 disabled={route.disabled}
46 className={menuButtonClass}
47 >
48 {content}
49 </button>
50 ) : route.link ? (
51 <Link
52 href={route.link}
53 onClick={onCloseSheet}
54 data-active={isActive}
55 className={menuButtonClass}
56 >
57 {content}
58 </Link>
59 ) : (
60 <span data-active={false} className={cn(menuButtonClass, 'cursor-default')}>
61 {content}
62 </span>
63 )}
64 </SidebarMenuItem>
65 )
66}