{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "theme-switcher",
  "title": "Theme Switcher",
  "author": "ncdai <dai@chanhdai.com>",
  "description": "Toggle between system, light, and dark themes in Next.js apps.",
  "dependencies": [
    "next-themes",
    "motion",
    "lucide-react"
  ],
  "files": [
    {
      "path": "src/registry/components/theme-switcher/theme-switcher.tsx",
      "content": "\"use client\"\n\nimport type { JSX } from \"react\"\nimport { useSyncExternalStore } from \"react\"\nimport { MonitorIcon, MoonIcon, SunIcon } from \"lucide-react\"\nimport { motion } from \"motion/react\"\nimport { useTheme } from \"next-themes\"\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      data-active={isActive}\n      className=\"relative flex size-8 items-center justify-center rounded-full text-muted-foreground transition-[color] hover:text-foreground data-[active=true]:text-foreground [&_svg]:size-4\"\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.span\n          layoutId=\"theme-option\"\n          transition={{ type: \"spring\", bounce: 0.3, duration: 0.6 }}\n          className=\"absolute inset-0 rounded-full border\"\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: <MoonIcon />,\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-clip rounded-full bg-background inset-ring-1 inset-ring-border\"\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",
      "target": "@components/theme-switcher.tsx"
    }
  ],
  "docs": "https://chanhdai.com/components/theme-switcher",
  "categories": [
    "controls"
  ],
  "type": "registry:component"
}