{"$schema":"https://ui.shadcn.com/schema/registry-item.json","name":"theme-switcher","type":"registry:ui","title":"theme-switcher","description":"A component to switch between light, dark and system theme.","author":"Hayden Bleasel <hello@haydenbleasel.com>","dependencies":["@radix-ui/react-use-controllable-state","lucide-react","motion"],"devDependencies":[],"registryDependencies":[],"files":[{"type":"registry:ui","path":"index.tsx","content":"\"use client\";\n\nimport { useControllableState } from \"@radix-ui/react-use-controllable-state\";\nimport { Monitor, Moon, Sun } from \"lucide-react\";\nimport { motion } from \"motion/react\";\nimport { useCallback, useEffect, useState } from \"react\";\nimport { cn } from \"@/lib/utils\";\n\nconst themes = [\n  {\n    key: \"system\",\n    icon: Monitor,\n    label: \"System theme\",\n  },\n  {\n    key: \"light\",\n    icon: Sun,\n    label: \"Light theme\",\n  },\n  {\n    key: \"dark\",\n    icon: Moon,\n    label: \"Dark theme\",\n  },\n];\n\nexport type ThemeSwitcherProps = {\n  value?: \"light\" | \"dark\" | \"system\";\n  onChange?: (theme: \"light\" | \"dark\" | \"system\") => void;\n  defaultValue?: \"light\" | \"dark\" | \"system\";\n  className?: string;\n};\n\nexport const ThemeSwitcher = ({\n  value,\n  onChange,\n  defaultValue = \"system\",\n  className,\n}: ThemeSwitcherProps) => {\n  const [theme, setTheme] = useControllableState({\n    defaultProp: defaultValue,\n    prop: value,\n    onChange,\n  });\n  const [mounted, setMounted] = useState(false);\n\n  const handleThemeClick = useCallback(\n    (themeKey: \"light\" | \"dark\" | \"system\") => {\n      setTheme(themeKey);\n    },\n    [setTheme]\n  );\n\n  // Prevent hydration mismatch\n  useEffect(() => {\n    setMounted(true);\n  }, []);\n\n  if (!mounted) {\n    return null;\n  }\n\n  return (\n    <div\n      className={cn(\n        \"relative isolate flex h-8 rounded-full bg-background p-1 ring-1 ring-border\",\n        className\n      )}\n    >\n      {themes.map(({ key, icon: Icon, label }) => {\n        const isActive = theme === key;\n\n        return (\n          <button\n            aria-label={label}\n            className=\"relative h-6 w-6 rounded-full\"\n            key={key}\n            onClick={() => handleThemeClick(key as \"light\" | \"dark\" | \"system\")}\n            type=\"button\"\n          >\n            {isActive && (\n              <motion.div\n                className=\"absolute inset-0 rounded-full bg-secondary\"\n                layoutId=\"activeTheme\"\n                transition={{ type: \"spring\", duration: 0.5 }}\n              />\n            )}\n            <Icon\n              className={cn(\n                \"relative z-10 m-auto h-4 w-4\",\n                isActive ? \"text-foreground\" : \"text-muted-foreground\"\n              )}\n            />\n          </button>\n        );\n      })}\n    </div>\n  );\n};\n","target":"components/kibo-ui/theme-switcher/index.tsx"}],"css":{}}