{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "theme-switcher",
  "type": "registry:component",
  "title": "Theme Switcher",
  "author": "ncdai <dai@chanhdai.com>",
  "description": "A theme switcher component for Next.js apps with next-themes and Tailwind CSS, supporting system, light, and dark modes.",
  "dependencies": [
    "next-themes",
    "lucide-react",
    "motion"
  ],
  "registryDependencies": [
    "@ncdai/utils"
  ],
  "files": [
    {
      "path": "src/registry/theme-switcher/theme-switcher.tsx",
      "content": "\"use client\";\n\nimport { MonitorIcon, MoonStarIcon, SunIcon } from \"lucide-react\";\nimport { motion } from \"motion/react\";\nimport { useTheme } from \"next-themes\";\nimport type { JSX } from \"react\";\nimport { useSyncExternalStore } from \"react\";\n\nimport { cn } from \"@/lib/utils\";\n\nfunction ThemeOption({\n  icon,\n  value,\n  isActive,\n  onClick,\n}: {\n  icon: JSX.Element;\n  value: string;\n  isActive?: boolean;\n  onClick: (value: string) => void;\n}) {\n  return (\n    <button\n      className={cn(\n        \"relative flex size-8 cursor-default items-center justify-center rounded-full transition-[color] [&_svg]:size-4\",\n        isActive\n          ? \"text-zinc-950 dark:text-zinc-50\"\n          : \"text-zinc-400 hover:text-zinc-950 dark:text-zinc-500 dark:hover:text-zinc-50\"\n      )}\n      role=\"radio\"\n      aria-checked={isActive}\n      aria-label={`Switch to ${value} theme`}\n      onClick={() => onClick(value)}\n    >\n      {icon}\n\n      {isActive && (\n        <motion.div\n          layoutId=\"theme-option\"\n          transition={{ type: \"spring\", bounce: 0.3, duration: 0.6 }}\n          className=\"absolute inset-0 rounded-full border border-zinc-200 dark:border-zinc-700\"\n        />\n      )}\n    </button>\n  );\n}\n\nconst THEME_OPTIONS = [\n  {\n    icon: <MonitorIcon />,\n    value: \"system\",\n  },\n  {\n    icon: <SunIcon />,\n    value: \"light\",\n  },\n  {\n    icon: <MoonStarIcon />,\n    value: \"dark\",\n  },\n];\n\nfunction ThemeSwitcher() {\n  const { theme, setTheme } = useTheme();\n\n  const isMounted = useSyncExternalStore(\n    () => () => {},\n    () => true,\n    () => false\n  );\n\n  if (!isMounted) {\n    return <div className=\"flex h-8 w-24\" />;\n  }\n\n  return (\n    <motion.div\n      key={String(isMounted)}\n      initial={{ opacity: 0 }}\n      animate={{ opacity: 1 }}\n      transition={{ duration: 0.3 }}\n      className=\"inline-flex items-center overflow-hidden rounded-full bg-white ring-1 ring-zinc-200 ring-inset dark:bg-zinc-950 dark:ring-zinc-700\"\n      role=\"radiogroup\"\n    >\n      {THEME_OPTIONS.map((option) => (\n        <ThemeOption\n          key={option.value}\n          icon={option.icon}\n          value={option.value}\n          isActive={theme === option.value}\n          onClick={setTheme}\n        />\n      ))}\n    </motion.div>\n  );\n}\n\nexport { ThemeSwitcher };\n",
      "type": "registry:component"
    }
  ],
  "docs": "https://chanhdai.com/components/theme-switcher-component"
}