TopLevelRouteItem.tsx 1.7 KB

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