{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "macos-sidebar",
  "type": "registry:component",
  "title": "macOS Sidebar",
  "description": "A premium macOS-style collapsible sidebar with smooth spring-driven width transitions, hover morphing, and tactile selection feedback.",
  "dependencies": [
    "@hugeicons/core-free-icons",
    "@hugeicons/react",
    "motion"
  ],
  "files": [
    {
      "path": "components/watermelon/macos-sidebar.tsx",
      "type": "registry:component",
      "content": "\"use client\";\n\nimport { PlusSignIcon, SidebarLeftIcon } from \"@hugeicons/core-free-icons\";\nimport { HugeiconsIcon } from \"@hugeicons/react\";\nimport { motion, AnimatePresence } from \"motion/react\";\nimport { useState, type ReactNode } from \"react\";\n\nexport interface MacOSSidebarProps {\n  items: string[];\n  defaultOpen?: boolean;\n  initialSelectedIndex?: number;\n  children?: ReactNode;\n  className?: string;\n}\n\nexport function MacOSSidebar({\n  items,\n  defaultOpen = true,\n  initialSelectedIndex = 0,\n  children,\n  className = \"\",\n}: MacOSSidebarProps) {\n  const [hoveredIndex, setHoveredIndex] = useState<number | null>(null);\n  const [selectedIndex, setSelectedIndex] =\n    useState<number>(initialSelectedIndex);\n  const [isOpen, setIsOpen] = useState<boolean>(defaultOpen);\n\n  return (\n    <div\n      className={`flex bg-neutral-200 dark:bg-neutral-900 rounded-3xl p-3 relative w-full sm:min-w-[480px] overflow-hidden ${className}`}\n    >\n      <motion.div\n        animate={{\n          width: isOpen ? 240 : 64,\n        }}\n        transition={{ type: \"spring\", bounce: 0.4, duration: 0.8 }}\n        className={`p-2 rounded-2xl shrink-0 flex flex-col items-start transition-colors duration-900 ease-out ${\n          isOpen ? \"bg-neutral-100 dark:bg-neutral-800\" : \"bg-transparent\"\n        }`}\n      >\n        <div\n          className={`flex items-center w-full ${\n            isOpen ? \"justify-end gap-4\" : \"justify-center\"\n          } text-neutral-700 dark:text-neutral-300 p-2 shrink-0`}\n        >\n          <AnimatePresence>\n            {isOpen && (\n              <motion.div\n                initial={{ opacity: 0, scale: 0.8 }}\n                animate={{ opacity: 1, scale: 1 }}\n                exit={{ opacity: 0, scale: 0.8 }}\n                transition={{ duration: 0.2 }}\n              >\n                <HugeiconsIcon\n                  icon={PlusSignIcon}\n                  className=\"size-5 cursor-pointer\"\n                />\n              </motion.div>\n            )}\n          </AnimatePresence>\n          <motion.div\n            layout\n            className=\"shrink-0 flex items-center justify-center\"\n          >\n            <HugeiconsIcon\n              icon={SidebarLeftIcon}\n              className=\"size-5 cursor-pointer\"\n              onClick={() => setIsOpen(!isOpen)}\n            />\n          </motion.div>\n        </div>\n\n        <AnimatePresence>\n          {isOpen && (\n            <motion.div\n              initial={{ opacity: 0, filter: \"blur(4px)\" }}\n              animate={{ opacity: 1, filter: \"blur(0px)\" }}\n              exit={{ opacity: 0, filter: \"blur(4px)\" }}\n              transition={{ duration: 0.2, ease: \"easeOut\" }}\n              className=\"flex flex-col gap-2 mt-4 w-full relative z-10 whitespace-nowrap\"\n              onMouseLeave={() => setHoveredIndex(null)}\n            >\n              {items.map((item, index) => (\n                <div\n                  key={item}\n                  className=\"relative cursor-pointer\"\n                  onMouseEnter={() => setHoveredIndex(index)}\n                  onClick={() => setSelectedIndex(index)}\n                >\n                  <AnimatePresence>\n                    {selectedIndex === index && (\n                      <motion.div\n                        className=\"absolute inset-0 z-0 bg-neutral-200 dark:bg-neutral-700 rounded-md\"\n                        initial={{ opacity: 0 }}\n                        animate={{ opacity: 1 }}\n                        exit={{ opacity: 0 }}\n                        transition={{ duration: 0.2, ease: \"easeOut\" }}\n                      />\n                    )}\n                  </AnimatePresence>\n                  <p\n                    className={`relative z-10 px-5 py-3 tracking-tight ${\n                      selectedIndex === index\n                        ? \"text-neutral-900 dark:text-neutral-100 font-medium\"\n                        : \"text-neutral-700 dark:text-neutral-200/50\"\n                    }`}\n                  >\n                    {item}\n                  </p>\n                  <AnimatePresence>\n                    {hoveredIndex === index && selectedIndex !== index && (\n                      <motion.span\n                        layoutId=\"sidebar-hover-bg\"\n                        className=\"absolute inset-0 z-0 bg-neutral-200/50 dark:bg-neutral-900/50 rounded-md\"\n                        initial={{ opacity: 0 }}\n                        animate={{ opacity: 1 }}\n                        exit={{ opacity: 0 }}\n                        transition={{\n                          type: \"spring\",\n                          stiffness: 350,\n                          damping: 30,\n                        }}\n                      />\n                    )}\n                  </AnimatePresence>\n                </div>\n              ))}\n            </motion.div>\n          )}\n        </AnimatePresence>\n      </motion.div>\n\n      <div className=\"flex-1 w-full h-full min-h-full overflow-y-auto z-0 pl-4 lg:pl-8\">\n        {children}\n      </div>\n    </div>\n  );\n}\n"
    }
  ]
}
