SidebarItem.tsx raw
1 import { Button, ButtonProps } from '@/components/ui/button'
2 import { useKeyboardNavigable } from '@/hooks/useKeyboardNavigable'
3 import { cn } from '@/lib/utils'
4 import { forwardRef, useCallback, useRef } from 'react'
5 import { useTranslation } from 'react-i18next'
6
7 const SidebarItem = forwardRef<
8 HTMLButtonElement,
9 ButtonProps & {
10 title: string
11 collapse: boolean
12 description?: string
13 active?: boolean
14 navIndex?: number
15 }
16 >(({ children, title, description, className, active, collapse, navIndex, onClick, ...props }, _ref) => {
17 const { t } = useTranslation()
18 const buttonRef = useRef<HTMLButtonElement>(null)
19
20 const handleActivate = useCallback(() => {
21 buttonRef.current?.click()
22 }, [])
23
24 const { ref: navRef, isSelected } = useKeyboardNavigable(0, navIndex ?? 0, {
25 meta: { type: 'sidebar', onActivate: handleActivate }
26 })
27
28 return (
29 <div ref={navRef}>
30 <Button
31 className={cn(
32 'flex shadow-none items-center transition-colors duration-500 bg-transparent m-0 rounded-lg gap-4 text-lg font-semibold',
33 collapse
34 ? 'w-12 h-12 p-3 [&_svg]:size-full'
35 : 'justify-start w-full h-auto py-2 px-3 [&_svg]:size-5',
36 active && 'text-primary hover:text-primary bg-primary/10 hover:bg-primary/10',
37 isSelected && 'ring-2 ring-primary ring-offset-2 ring-offset-background',
38 className
39 )}
40 variant="ghost"
41 title={t(title)}
42 ref={buttonRef}
43 onClick={onClick}
44 {...props}
45 >
46 {children}
47 {!collapse && <div>{t(description ?? title)}</div>}
48 </Button>
49 </div>
50 )
51 })
52 SidebarItem.displayName = 'SidebarItem'
53 export default SidebarItem
54