{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "theme-toggle",
  "title": "Theme Toggle",
  "description": "A control for switching between light, dark and system colour themes.",
  "dependencies": [
    "@untitledui/icons@^0.0.22",
    "next-themes@^0.4.6"
  ],
  "registryDependencies": [
    "@nx-ui/button",
    "@nx-ui/dropdown-menu",
    "@nx-ui/utils"
  ],
  "files": [
    {
      "path": "components/blocks/theme-toggle.tsx",
      "content": "\"use client\"\n\nimport * as React from \"react\"\nimport { Sun, Moon01, Monitor01 } from \"@untitledui/icons\"\nimport { useTheme } from \"next-themes\"\n\nimport { cn } from \"@/lib/utils\"\nimport { Button } from \"@/components/ui/button\"\nimport {\n  DropdownMenu,\n  DropdownMenuContent,\n  DropdownMenuRadioGroup,\n  DropdownMenuRadioItem,\n  DropdownMenuTrigger,\n} from \"@/components/ui/dropdown-menu\"\n\ntype ThemeValue = \"light\" | \"dark\" | \"system\"\n\nconst themeOptions: { value: ThemeValue; label: string; icon: React.ComponentType<{ className?: string }> }[] = [\n  { value: \"light\", label: \"Light\", icon: Sun },\n  { value: \"dark\", label: \"Dark\", icon: Moon01 },\n  { value: \"system\", label: \"System\", icon: Monitor01 },\n]\n\n/** Avoids a hydration mismatch — next-themes is undefined on the server. */\nfunction useMounted() {\n  const [mounted, setMounted] = React.useState(false)\n  React.useEffect(() => setMounted(true), [])\n  return mounted\n}\n\n/**\n * ThemeToggle — a standalone icon button that opens a light/dark/system menu\n * (the default), or, with `variant=\"cycle\"`, a single button that cycles\n * light → dark → system on click. Driven by next-themes.\n */\nfunction ThemeToggle({\n  variant = \"menu\",\n  className,\n  ...props\n}: Omit<React.ComponentProps<typeof Button>, \"children\" | \"variant\"> & {\n  variant?: \"menu\" | \"cycle\"\n}) {\n  const { theme, setTheme, resolvedTheme } = useTheme()\n  const mounted = useMounted()\n\n  const CurrentIcon = resolvedTheme === \"dark\" ? Moon01 : Sun\n\n  if (variant === \"cycle\") {\n    return (\n      <Button\n        variant=\"ghost\"\n        size=\"icon-sm\"\n        aria-label=\"Toggle theme\"\n        className={cn(className)}\n        onClick={() => {\n          const order: ThemeValue[] = [\"light\", \"dark\", \"system\"]\n          const current = (theme as ThemeValue) ?? \"system\"\n          const next = order[(order.indexOf(current) + 1) % order.length]\n          setTheme(next)\n        }}\n        {...props}\n      >\n        {mounted ? <CurrentIcon /> : <Sun />}\n        <span className=\"sr-only\">Toggle theme</span>\n      </Button>\n    )\n  }\n\n  return (\n    <DropdownMenu>\n      <DropdownMenuTrigger\n        render={\n          <Button\n            variant=\"ghost\"\n            size=\"icon-sm\"\n            aria-label=\"Toggle theme\"\n            className={cn(className)}\n            {...props}\n          />\n        }\n      >\n        {mounted ? <CurrentIcon /> : <Sun />}\n        <span className=\"sr-only\">Toggle theme</span>\n      </DropdownMenuTrigger>\n      <DropdownMenuContent align=\"end\" className=\"min-w-40\">\n        <ThemeToggleMenuItems />\n      </DropdownMenuContent>\n    </DropdownMenu>\n  )\n}\n\n/**\n * ThemeToggleMenuItems — the light/dark/system radio group, for embedding\n * inside another DropdownMenu (e.g. the user menu). Must be rendered within a\n * DropdownMenuContent.\n */\nfunction ThemeToggleMenuItems() {\n  const { theme, setTheme } = useTheme()\n  const mounted = useMounted()\n\n  return (\n    <DropdownMenuRadioGroup\n      value={(mounted && theme) || \"system\"}\n      onValueChange={setTheme}\n    >\n      {themeOptions.map(({ value, label, icon: Icon }) => (\n        <DropdownMenuRadioItem key={value} value={value} className=\"pl-2.5\">\n          <Icon className=\"size-4 text-fg-quaternary\" />\n          {label}\n        </DropdownMenuRadioItem>\n      ))}\n    </DropdownMenuRadioGroup>\n  )\n}\n\nexport { ThemeToggle, ThemeToggleMenuItems }\n",
      "type": "registry:component"
    }
  ],
  "type": "registry:block"
}