navLink.tsx 1.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263
  1. 'use client'
  2. import { useSelectedLayoutSegment } from 'next/navigation'
  3. import Link from 'next/link'
  4. import classNames from '@/utils/classnames'
  5. export type NavIcon = React.ComponentType<
  6. React.PropsWithoutRef<React.ComponentProps<'svg'>> & {
  7. title?: string | undefined
  8. titleId?: string | undefined
  9. }
  10. >
  11. export type NavLinkProps = {
  12. name: string
  13. href: string
  14. iconMap: {
  15. selected: NavIcon
  16. normal: NavIcon
  17. }
  18. mode?: string
  19. }
  20. export default function NavLink({
  21. name,
  22. href,
  23. iconMap,
  24. mode = 'expand',
  25. }: NavLinkProps) {
  26. const segment = useSelectedLayoutSegment()
  27. const formattedSegment = (() => {
  28. let res = segment?.toLowerCase()
  29. // logs and annotations use the same nav
  30. if (res === 'annotations')
  31. res = 'logs'
  32. return res
  33. })()
  34. const isActive = href.toLowerCase().split('/')?.pop() === formattedSegment
  35. const NavIcon = isActive ? iconMap.selected : iconMap.normal
  36. return (
  37. <Link
  38. key={name}
  39. href={href}
  40. className={classNames(
  41. isActive ? 'bg-state-accent-active text-text-accent font-semibold' : 'text-components-menu-item-text hover:bg-gray-100 hover:text-components-menu-item-text-hover',
  42. 'group flex items-center h-9 rounded-md py-2 text-sm font-normal',
  43. mode === 'expand' ? 'px-3' : 'px-2.5',
  44. )}
  45. title={mode === 'collapse' ? name : ''}
  46. >
  47. <NavIcon
  48. className={classNames(
  49. 'h-4 w-4 flex-shrink-0',
  50. mode === 'expand' ? 'mr-2' : 'mr-0',
  51. )}
  52. aria-hidden="true"
  53. />
  54. {mode === 'expand' && name}
  55. </Link>
  56. )
  57. }