{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "sidebar",
  "type": "registry:ui",
  "description": "Collapsible sidebar with mobile drawer, tooltips, and keyboard shortcut",
  "dependencies": [
    "class-variance-authority",
    "lucide-react"
  ],
  "registryDependencies": [
    "utils",
    "button",
    "sheet",
    "tooltip"
  ],
  "files": [
    {
      "path": "registry/default/ui/sidebar.tsx",
      "content": "import * as React from 'react'\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport { PanelLeft } from 'lucide-react'\nimport { cn } from '@/lib/utils'\nimport { Button } from '@/components/ui/button'\nimport { Sheet, SheetContent } from '@/components/ui/sheet'\nimport {\n  Tooltip,\n  TooltipContent,\n  TooltipTrigger,\n} from '@/components/ui/tooltip'\n\nconst SIDEBAR_COOKIE_NAME = 'sidebar:state'\nconst SIDEBAR_COOKIE_MAX_AGE = 60 * 60 * 24 * 7 // 7 days\nconst SIDEBAR_WIDTH = '16rem'\nconst SIDEBAR_WIDTH_COLLAPSED = '4rem'\nconst SIDEBAR_WIDTH_MOBILE = '18rem'\nconst SIDEBAR_KEYBOARD_SHORTCUT = 'b'\n\n// Context\ninterface SidebarContextValue {\n  state: 'expanded' | 'collapsed'\n  open: boolean\n  setOpen: (open: boolean) => void\n  openMobile: boolean\n  setOpenMobile: (open: boolean) => void\n  isMobile: boolean\n  toggleSidebar: () => void\n}\n\nconst SidebarContext = React.createContext<SidebarContextValue | null>(null)\n\nfunction useSidebar() {\n  const context = React.useContext(SidebarContext)\n  if (!context) {\n    throw new Error('useSidebar must be used within a <SidebarProvider />')\n  }\n  return context\n}\n\n// Provider\ninterface SidebarProviderProps extends React.HTMLAttributes<HTMLDivElement> {\n  defaultOpen?: boolean\n  open?: boolean\n  onOpenChange?: (open: boolean) => void\n}\n\nconst SidebarProvider = React.forwardRef<HTMLDivElement, SidebarProviderProps>(\n  (\n    {\n      defaultOpen = true,\n      open: controlledOpen,\n      onOpenChange,\n      className,\n      style,\n      children,\n      ...props\n    },\n    ref\n  ) => {\n    const [uncontrolledOpen, setUncontrolledOpen] = React.useState(defaultOpen)\n    const [openMobile, setOpenMobile] = React.useState(false)\n    const [isMobile, setIsMobile] = React.useState(false)\n\n    const isControlled = controlledOpen !== undefined\n    const open = isControlled ? controlledOpen : uncontrolledOpen\n\n    const setOpen = React.useCallback(\n      (value: boolean) => {\n        if (!isControlled) {\n          setUncontrolledOpen(value)\n        }\n        onOpenChange?.(value)\n\n        // Save to cookie\n        document.cookie = `${SIDEBAR_COOKIE_NAME}=${value}; path=/; max-age=${SIDEBAR_COOKIE_MAX_AGE}`\n      },\n      [isControlled, onOpenChange]\n    )\n\n    const toggleSidebar = React.useCallback(() => {\n      if (isMobile) {\n        setOpenMobile((prev) => !prev)\n      } else {\n        setOpen(!open)\n      }\n    }, [isMobile, open, setOpen])\n\n    // Check if mobile\n    React.useEffect(() => {\n      const checkMobile = () => {\n        setIsMobile(window.innerWidth < 768)\n      }\n      checkMobile()\n      window.addEventListener('resize', checkMobile)\n      return () => window.removeEventListener('resize', checkMobile)\n    }, [])\n\n    // Keyboard shortcut\n    React.useEffect(() => {\n      const handleKeyDown = (e: KeyboardEvent) => {\n        if (\n          e.key === SIDEBAR_KEYBOARD_SHORTCUT &&\n          (e.metaKey || e.ctrlKey) &&\n          !e.shiftKey &&\n          !e.altKey\n        ) {\n          e.preventDefault()\n          toggleSidebar()\n        }\n      }\n\n      window.addEventListener('keydown', handleKeyDown)\n      return () => window.removeEventListener('keydown', handleKeyDown)\n    }, [toggleSidebar])\n\n    const state = open ? 'expanded' : 'collapsed'\n\n    const contextValue = React.useMemo<SidebarContextValue>(\n      () => ({\n        state,\n        open,\n        setOpen,\n        openMobile,\n        setOpenMobile,\n        isMobile,\n        toggleSidebar,\n      }),\n      [state, open, setOpen, openMobile, setOpenMobile, isMobile, toggleSidebar]\n    )\n\n    return (\n      <SidebarContext.Provider value={contextValue}>\n        <div\n          ref={ref}\n          style={\n            {\n              '--sidebar-width': SIDEBAR_WIDTH,\n              '--sidebar-width-collapsed': SIDEBAR_WIDTH_COLLAPSED,\n              ...style,\n            } as React.CSSProperties\n          }\n          className={cn(\n            'group/sidebar-wrapper flex min-h-screen w-full',\n            className\n          )}\n          {...props}\n        >\n          {children}\n        </div>\n      </SidebarContext.Provider>\n    )\n  }\n)\nSidebarProvider.displayName = 'SidebarProvider'\n\n// Main Sidebar\nconst sidebarVariants = cva(\n  'relative flex h-full flex-col border-r-3 border-foreground bg-background transition-all duration-300 ease-out',\n  {\n    variants: {\n      collapsible: {\n        none: 'w-[var(--sidebar-width)]',\n        icon: 'w-[var(--sidebar-width)] group-data-[state=collapsed]/sidebar:w-[var(--sidebar-width-collapsed)]',\n        hidden: 'w-[var(--sidebar-width)] group-data-[state=collapsed]/sidebar:w-0 group-data-[state=collapsed]/sidebar:border-0 group-data-[state=collapsed]/sidebar:overflow-hidden',\n      },\n      side: {\n        left: '',\n        right: 'border-r-0 border-l-3',\n      },\n    },\n    defaultVariants: {\n      collapsible: 'icon',\n      side: 'left',\n    },\n  }\n)\n\ninterface SidebarProps\n  extends React.HTMLAttributes<HTMLDivElement>,\n    VariantProps<typeof sidebarVariants> {}\n\nconst Sidebar = React.forwardRef<HTMLDivElement, SidebarProps>(\n  ({ side = 'left', collapsible = 'icon', className, children, ...props }, ref) => {\n    const { isMobile, state, openMobile, setOpenMobile } = useSidebar()\n\n    if (isMobile) {\n      return (\n        <Sheet open={openMobile} onOpenChange={setOpenMobile}>\n          <SheetContent\n            side={side === 'left' ? 'left' : 'right'}\n            className=\"w-[var(--sidebar-width-mobile)] p-0\"\n            style={{ '--sidebar-width-mobile': SIDEBAR_WIDTH_MOBILE } as React.CSSProperties}\n          >\n            <div className=\"flex h-full flex-col\">{children}</div>\n          </SheetContent>\n        </Sheet>\n      )\n    }\n\n    return (\n      <div\n        ref={ref}\n        data-state={state}\n        data-collapsible={collapsible}\n        className=\"group/sidebar hidden md:block\"\n      >\n        <div\n          className={cn(sidebarVariants({ collapsible, side }), className)}\n          {...props}\n        >\n          {children}\n        </div>\n      </div>\n    )\n  }\n)\nSidebar.displayName = 'Sidebar'\n\n// Sidebar Toggle\nconst SidebarToggle = React.forwardRef<\n  HTMLButtonElement,\n  React.ComponentProps<typeof Button>\n>(({ className, ...props }, ref) => {\n  const { toggleSidebar, state } = useSidebar()\n\n  return (\n    <Button\n      ref={ref}\n      variant=\"outline\"\n      size=\"icon\"\n      className={cn('h-8 w-8 transition-transform duration-300', className)}\n      onClick={toggleSidebar}\n      {...props}\n    >\n      <PanelLeft\n        className={cn(\n          'h-4 w-4 transition-transform duration-300',\n          state === 'collapsed' && 'rotate-180'\n        )}\n      />\n      <span className=\"sr-only\">Toggle Sidebar</span>\n    </Button>\n  )\n})\nSidebarToggle.displayName = 'SidebarToggle'\n\n// Sidebar Header\nconst SidebarHeader = React.forwardRef<\n  HTMLDivElement,\n  React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => (\n  <div\n    ref={ref}\n    className={cn(\n      'flex items-center border-b-3 border-foreground p-4',\n      'group-data-[state=collapsed]/sidebar:justify-center',\n      className\n    )}\n    {...props}\n  />\n))\nSidebarHeader.displayName = 'SidebarHeader'\n\n// Sidebar Content\nconst SidebarContent = React.forwardRef<\n  HTMLDivElement,\n  React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => (\n  <div\n    ref={ref}\n    className={cn('flex-1 overflow-auto p-4', className)}\n    {...props}\n  />\n))\nSidebarContent.displayName = 'SidebarContent'\n\n// Sidebar Footer\nconst SidebarFooter = React.forwardRef<\n  HTMLDivElement,\n  React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => (\n  <div\n    ref={ref}\n    className={cn(\n      'flex items-center border-t-3 border-foreground p-4',\n      'group-data-[state=collapsed]/sidebar:justify-center',\n      className\n    )}\n    {...props}\n  />\n))\nSidebarFooter.displayName = 'SidebarFooter'\n\n// Sidebar Group\nconst SidebarGroup = React.forwardRef<\n  HTMLDivElement,\n  React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => (\n  <div\n    ref={ref}\n    className={cn('space-y-2', className)}\n    {...props}\n  />\n))\nSidebarGroup.displayName = 'SidebarGroup'\n\n// Sidebar Group Label\nconst SidebarGroupLabel = React.forwardRef<\n  HTMLDivElement,\n  React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => {\n  const context = React.useContext(SidebarContext)\n  const state = context?.state ?? 'expanded'\n\n  return (\n    <div\n      ref={ref}\n      className={cn(\n        'px-2 py-1 text-xs font-bold uppercase tracking-wide text-muted-foreground',\n        'transition-opacity duration-200',\n        state === 'collapsed' && 'opacity-0 hidden',\n        className\n      )}\n      {...props}\n    />\n  )\n})\nSidebarGroupLabel.displayName = 'SidebarGroupLabel'\n\n// Sidebar Item\nconst sidebarItemVariants = cva(\n  'flex w-full items-center gap-3 px-3 py-2 text-sm transition-all duration-150',\n  {\n    variants: {\n      variant: {\n        default: 'hover:bg-muted',\n        active: 'bg-accent shadow-[4px_4px_0px_hsl(var(--shadow-color))]',\n      },\n    },\n    defaultVariants: {\n      variant: 'default',\n    },\n  }\n)\n\ninterface SidebarItemProps\n  extends React.ButtonHTMLAttributes<HTMLButtonElement>,\n    VariantProps<typeof sidebarItemVariants> {\n  icon?: React.ReactNode\n  tooltip?: string\n}\n\nconst SidebarItem = React.forwardRef<HTMLButtonElement, SidebarItemProps>(\n  ({ variant, icon, tooltip, className, children, ...props }, ref) => {\n    const context = React.useContext(SidebarContext)\n    const isCollapsed = context?.state === 'collapsed'\n\n    const button = (\n      <button\n        ref={ref}\n        className={cn(\n          sidebarItemVariants({ variant }),\n          isCollapsed && 'justify-center px-2',\n          className\n        )}\n        {...props}\n      >\n        {icon && <span className=\"shrink-0\">{icon}</span>}\n        {!isCollapsed && <span className=\"truncate\">{children}</span>}\n      </button>\n    )\n\n    if (isCollapsed && tooltip) {\n      return (\n        <Tooltip>\n          <TooltipTrigger asChild>{button}</TooltipTrigger>\n          <TooltipContent side=\"right\">{tooltip}</TooltipContent>\n        </Tooltip>\n      )\n    }\n\n    return button\n  }\n)\nSidebarItem.displayName = 'SidebarItem'\n\n// Sidebar Separator\nconst SidebarSeparator = React.forwardRef<\n  HTMLDivElement,\n  React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => (\n  <div\n    ref={ref}\n    className={cn('mx-2 h-[3px] bg-foreground', className)}\n    {...props}\n  />\n))\nSidebarSeparator.displayName = 'SidebarSeparator'\n\n// Sidebar Inset (main content wrapper)\nconst SidebarInset = React.forwardRef<\n  HTMLDivElement,\n  React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => (\n  <div\n    ref={ref}\n    className={cn('flex-1 overflow-auto', className)}\n    {...props}\n  />\n))\nSidebarInset.displayName = 'SidebarInset'\n\nexport {\n  Sidebar,\n  SidebarProvider,\n  SidebarHeader,\n  SidebarContent,\n  SidebarFooter,\n  SidebarGroup,\n  SidebarGroupLabel,\n  SidebarItem,\n  SidebarSeparator,\n  SidebarToggle,\n  SidebarInset,\n  useSidebar,\n  sidebarVariants,\n  sidebarItemVariants,\n}\n",
      "type": "registry:ui",
      "target": "components/ui/sidebar.tsx"
    }
  ]
}