{ "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "theme-toggle-glass", "type": "registry:component", "title": "Theme Toggle Glass", "description": "Theme cycling button that switches between Light, Aurora, and Glass themes.\n * Displays animated icon transitions with theme-aware styling.\n *\n * ## Features", "dependencies": [ "lucide-react", "react", "shadcn-glass-ui" ], "registryDependencies": [ "cn", "theme-provider" ], "files": [ { "path": "components/glass/atomic/theme-toggle-glass.tsx", "type": "registry:component", "content": "/**\n * ThemeToggleGlass Component\n *\n * Theme cycling button that switches between Light, Aurora, and Glass themes.\n * Displays animated icon transitions with theme-aware styling.\n *\n * ## Features\n * - One-click theme cycling through 3 themes (light → aurora → glass → light)\n * - Animated icon transitions (Sun → Moon → Palette)\n * - Built on IconButtonGlass styling for consistency\n * - Theme preview via icon (shows NEXT theme, not current)\n * - Optional text label showing next theme name\n * - Responsive label visibility (hidden on mobile by default)\n * - Integrates with useTheme hook for global theme state\n * - Accessible button with descriptive aria-label\n * - Keyboard accessible (Enter/Space to activate)\n * - Custom toggle handler support for advanced use cases\n *\n * ## CSS Variables\n * Uses IconButtonGlass CSS variables:\n * - `--card-subtle-bg` - Button background\n * - `--card-subtle-border` - Button border\n * - `--text-secondary` - Icon and label color\n *\n * @example Basic theme toggle\n * ```tsx\n * import { ThemeToggleGlass } from 'shadcn-glass-ui'\n *\n * function Header() {\n * return (\n * \n * )\n * }\n * ```\n *\n * @example Icon-only (no label)\n * ```tsx\n * \n * ```\n *\n * @example Custom toggle handler\n * ```tsx\n * function AdvancedThemeToggle() {\n * const handleToggle = () => {\n * console.log('Theme changing...')\n * // Custom logic here\n * }\n *\n * return \n * }\n * ```\n *\n * @example Larger icon size\n * ```tsx\n * \n * ```\n *\n * @accessibility\n * - Descriptive aria-label indicates next theme (e.g., \"Switch to Aurora theme\")\n * - Focus ring visible for keyboard navigation\n * - Keyboard activation via Enter or Space key\n * - Icon provides visual feedback for theme state\n * - Hover scale animation (105%) indicates interactivity\n *\n * @since v1.0.0\n */\n\nimport { forwardRef, type ButtonHTMLAttributes, type CSSProperties } from 'react';\nimport { Sun, Moon, Palette } from 'lucide-react';\nimport { cn } from '@/lib/utils';\nimport { useTheme, type ThemeName } from '@/lib/theme-context';\nimport '@/glass-theme.css';\n\n// ========================================\n// CONFIGURATION\n// ========================================\n\nconst themes: ThemeName[] = ['light', 'aurora', 'glass'];\n\nconst themeConfig: Record = {\n light: { label: 'Light', icon: Sun },\n aurora: { label: 'Aurora', icon: Moon },\n glass: { label: 'Glass', icon: Palette },\n};\n\n// ========================================\n// PROPS INTERFACE\n// ========================================\n\n/**\n * Props for ThemeToggleGlass component.\n *\n * Extends standard button attributes with theme-specific props.\n * Integrates with useTheme hook for automatic theme cycling.\n *\n * @example\n * ```tsx\n * const props: ThemeToggleGlassProps = {\n * iconOnly: true,\n * iconSize: 24,\n * onToggle: () => console.log('Theme changed'),\n * };\n * ```\n */\nexport interface ThemeToggleGlassProps extends ButtonHTMLAttributes {\n /**\n * Custom theme toggle handler.\n *\n * Overrides default cycleTheme behavior from useTheme hook.\n * Useful for adding analytics, animations, or custom theme logic.\n *\n * @example\n * ```tsx\n * {\n * trackEvent('theme_changed')\n * // Custom logic\n * }}\n * />\n * ```\n */\n readonly onToggle?: () => void;\n\n /**\n * Icon size in pixels.\n *\n * Controls the size of the Sun, Moon, or Palette icon.\n *\n * @default 20\n * @example\n * ```tsx\n * // Larger icon for prominent placement\n * \n *\n * // Smaller icon for compact toolbar\n * \n * ```\n */\n readonly iconSize?: number;\n\n /**\n * Show icon only (hide label).\n *\n * When `false`, displays theme name label on desktop (hidden on mobile).\n * When `true`, only shows icon on all screen sizes.\n *\n * @default false\n * @example\n * ```tsx\n * // Icon with label (desktop only)\n * \n *\n * // Icon only (all screens)\n * \n * ```\n */\n readonly iconOnly?: boolean;\n}\n\n// ========================================\n// COMPONENT\n// ========================================\n\nexport const ThemeToggleGlass = forwardRef(\n ({ onToggle, iconSize = 20, iconOnly = false, className, ...props }, ref) => {\n const { theme, cycleTheme } = useTheme();\n\n const nextTheme = themes[(themes.indexOf(theme) + 1) % themes.length];\n const NextIcon = themeConfig[nextTheme].icon;\n const nextLabel = themeConfig[nextTheme].label;\n\n const buttonStyles: CSSProperties = {\n background: 'var(--card-subtle-bg)',\n border: '1px solid var(--card-subtle-border)',\n };\n\n const iconStyles: CSSProperties = {\n color: 'var(--text-secondary)',\n };\n\n return (\n \n
\n \n {!iconOnly && (\n \n {nextLabel}\n \n )}\n
\n \n );\n }\n);\n\nThemeToggleGlass.displayName = 'ThemeToggleGlass';\n" } ], "categories": [ "atomic" ] }