{
  "name": "sidebar",
  "type": "registry:ui",
  "dependencies": [
    "@tabler/icons-react",
    "motion"
  ],
  "files": [
    {
      "path": "components/ui/sidebar.tsx",
      "content": "\"use client\";\nimport { cn } from \"@/lib/utils\";\nimport React, { useState, createContext, useContext } from \"react\";\nimport { AnimatePresence, motion } from \"motion/react\";\nimport { IconMenu2, IconX } from \"@tabler/icons-react\";\n\ninterface Links {\n  label: string;\n  href: string;\n  icon: React.JSX.Element | React.ReactNode;\n}\n\ninterface SidebarContextProps {\n  open: boolean;\n  setOpen: React.Dispatch<React.SetStateAction<boolean>>;\n  animate: boolean;\n}\n\nconst SidebarContext = createContext<SidebarContextProps | undefined>(\n  undefined\n);\n\nexport const useSidebar = () => {\n  const context = useContext(SidebarContext);\n  if (!context) {\n    throw new Error(\"useSidebar must be used within a SidebarProvider\");\n  }\n  return context;\n};\n\nexport const SidebarProvider = ({\n  children,\n  open: openProp,\n  setOpen: setOpenProp,\n  animate = true,\n}: {\n  children: React.ReactNode;\n  open?: boolean;\n  setOpen?: React.Dispatch<React.SetStateAction<boolean>>;\n  animate?: boolean;\n}) => {\n  const [openState, setOpenState] = useState(false);\n\n  const open = openProp !== undefined ? openProp : openState;\n  const setOpen = setOpenProp !== undefined ? setOpenProp : setOpenState;\n\n  return (\n    <SidebarContext.Provider value={{ open, setOpen, animate: animate }}>\n      {children}\n    </SidebarContext.Provider>\n  );\n};\n\nexport const Sidebar = ({\n  children,\n  open,\n  setOpen,\n  animate,\n}: {\n  children: React.ReactNode;\n  open?: boolean;\n  setOpen?: React.Dispatch<React.SetStateAction<boolean>>;\n  animate?: boolean;\n}) => {\n  return (\n    <SidebarProvider open={open} setOpen={setOpen} animate={animate}>\n      {children}\n    </SidebarProvider>\n  );\n};\n\nexport const SidebarBody = (props: React.ComponentProps<typeof motion.div>) => {\n  return (\n    <>\n      <DesktopSidebar {...props} />\n      <MobileSidebar {...(props as React.ComponentProps<\"div\">)} />\n    </>\n  );\n};\n\nexport const DesktopSidebar = ({\n  className,\n  children,\n  ...props\n}: React.ComponentProps<typeof motion.div>) => {\n  const { open, setOpen, animate } = useSidebar();\n  return (\n    <>\n      <motion.div\n        className={cn(\n          \"h-full px-4 py-4 hidden  md:flex md:flex-col bg-neutral-100 dark:bg-neutral-800 w-[300px] shrink-0\",\n          className\n        )}\n        animate={{\n          width: animate ? (open ? \"300px\" : \"60px\") : \"300px\",\n        }}\n        onMouseEnter={() => setOpen(true)}\n        onMouseLeave={() => setOpen(false)}\n        {...props}\n      >\n        {children}\n      </motion.div>\n    </>\n  );\n};\n\nexport const MobileSidebar = ({\n  className,\n  children,\n  ...props\n}: React.ComponentProps<\"div\">) => {\n  const { open, setOpen } = useSidebar();\n  return (\n    <>\n      <div\n        className={cn(\n          \"h-10 px-4 py-4 flex flex-row md:hidden  items-center justify-between bg-neutral-100 dark:bg-neutral-800 w-full\"\n        )}\n        {...props}\n      >\n        <div className=\"flex justify-end z-20 w-full\">\n          <IconMenu2\n            className=\"text-neutral-800 dark:text-neutral-200\"\n            onClick={() => setOpen(!open)}\n          />\n        </div>\n        <AnimatePresence>\n          {open && (\n            <motion.div\n              initial={{ x: \"-100%\", opacity: 0 }}\n              animate={{ x: 0, opacity: 1 }}\n              exit={{ x: \"-100%\", opacity: 0 }}\n              transition={{\n                duration: 0.3,\n                ease: \"easeInOut\",\n              }}\n              className={cn(\n                \"fixed h-full w-full inset-0 bg-white dark:bg-neutral-900 p-10 z-[100] flex flex-col justify-between\",\n                className\n              )}\n            >\n              <div\n                className=\"absolute right-10 top-10 z-50 text-neutral-800 dark:text-neutral-200\"\n                onClick={() => setOpen(!open)}\n              >\n                <IconX />\n              </div>\n              {children}\n            </motion.div>\n          )}\n        </AnimatePresence>\n      </div>\n    </>\n  );\n};\n\nexport const SidebarLink = ({\n  link,\n  className,\n  ...props\n}: {\n  link: Links;\n  className?: string;\n}) => {\n  const { open, animate } = useSidebar();\n  return (\n    <a\n      href={link.href}\n      className={cn(\n        \"flex items-center justify-start gap-2  group/sidebar py-2\",\n        className\n      )}\n      {...props}\n    >\n      {link.icon}\n\n      <motion.span\n        animate={{\n          display: animate ? (open ? \"inline-block\" : \"none\") : \"inline-block\",\n          opacity: animate ? (open ? 1 : 0) : 1,\n        }}\n        className=\"text-neutral-700 dark:text-neutral-200 text-sm group-hover/sidebar:translate-x-1 transition duration-150 whitespace-pre inline-block !p-0 !m-0\"\n      >\n        {link.label}\n      </motion.span>\n    </a>\n  );\n};\n",
      "type": "registry:ui",
      "target": "components/ui/sidebar.tsx"
    }
  ],
  "author": "Manu Arora <hi@manuarora.in>",
  "title": "Sidebar"
}