Add this component

npx zentauri-ui add toggle

Accessibility notes

Keyboard accessible controls with labels, focus-visible rings, and state attributes. Keep visible labels or aria-labels when copying snippets.

Dependency notes

Static imports do not pull framer-motion. Use the animated entry only when you want motion and have framer-motion installed.

Forms

Toggles for binary settings

Toggles represent boolean settings with immediate visual state. Use them in React settings panels and Next.js account pages where checkboxes feel too form-heavy.

Examples

Neutral appearance with a spring thumb animation.


Toggle variants examples

Track colors by appearance and thumb scale by size. Code uses a Variant: lead-in per row.


All appearances

Every shipped appearance token at a glance. Click any swatch to load it into the playground above.

default
success
destructive
neutral
indigo
purple
pink
orange
yellow
green
teal
cyan
lime
emerald
rose
slate
zinc
gray
stone
gradient-blue
gradient-green
gradient-red
gradient-yellow
gradient-purple
gradient-teal
gradient-indigo
gradient-pink
gradient-orange
blue
mint
ocean
sapphire
lavender
ruby
red
royal
electric
forest
sunset
magenta
crimson
aqua
plum















































Controlled: Unchecked


Toggle API

Generated from the package prop types and variant definitions.

Toggle

ToggleProps

Variants

PropTypeDefault
size
lgmdsm
md
thumbColor
aquabluecrimsoncyandefaultdestructiveelectricemeraldforestgradient-bluegradient-greengradient-indigo+31
default

State

PropTypeDefault
checkedboolean | undefinednone
defaultCheckedboolean | undefinednone
onCheckedChange((checked: boolean) => void) | undefinednone

Behavior

PropTypeDefault
appearance'default' | 'blue' | 'cyan' | 'green' | 'lime' | 'mint' | 'ocean' | 'sapphire' | 'lavender' | 'ruby' | 'red' | 'slate' | 'zinc' | 'stone' | 'royal' | 'electric' | 'forest' | 'sunset' | 'magenta' | 'crimson' | 'aqua' | 'plum' | 'rose' | 'purple' | 'pink' | 'orange' | 'yellow' | 'teal' | 'indigo' | 'emerald' | 'gradient-blue' | 'gradient-green' | 'gradient-red' | 'gradient-yellow' | 'gradient-purple' | 'gradient-teal' | 'gradient-indigo' | 'gradient-pink' | 'gradient-orange' | 'success' | 'gray' | 'destructive' | 'neutral' | null | undefinednone

Content

PropTypeDefault
childrenReactNodenone
Inherited HTML props
PropTypeDefault
classNamestring | undefinednone
idstring | undefinednone
onClickMouseEventHandler<HTMLButtonElement> | undefinednone
styleCSSProperties | undefinednone
titlestring | undefinednone

ToggleThumbVariant

ToggleThumbVariantProps

Behavior

PropTypeDefault
size'md' | 'sm' | 'lg' | null | undefinednone
thumbColor'default' | 'blue' | 'cyan' | 'green' | 'lime' | 'mint' | 'ocean' | 'sapphire' | 'lavender' | 'ruby' | 'red' | 'slate' | 'zinc' | 'stone' | 'royal' | 'electric' | 'forest' | 'sunset' | 'magenta' | 'crimson' | 'aqua' | 'plum' | 'rose' | 'purple' | 'pink' | 'orange' | 'yellow' | 'teal' | 'indigo' | 'emerald' | 'gradient-blue' | 'gradient-green' | 'gradient-red' | 'gradient-yellow' | 'gradient-purple' | 'gradient-teal' | 'gradient-indigo' | 'gradient-pink' | 'gradient-orange' | 'success' | 'gray' | 'destructive' | 'neutral' | null | undefinednone

ToggleTrackVariant

ToggleTrackVariantProps

Behavior

PropTypeDefault
appearance'default' | 'blue' | 'cyan' | 'green' | 'lime' | 'mint' | 'ocean' | 'sapphire' | 'lavender' | 'ruby' | 'red' | 'slate' | 'zinc' | 'stone' | 'royal' | 'electric' | 'forest' | 'sunset' | 'magenta' | 'crimson' | 'aqua' | 'plum' | 'rose' | 'purple' | 'pink' | 'orange' | 'yellow' | 'teal' | 'indigo' | 'emerald' | 'gradient-blue' | 'gradient-green' | 'gradient-red' | 'gradient-yellow' | 'gradient-purple' | 'gradient-teal' | 'gradient-indigo' | 'gradient-pink' | 'gradient-orange' | 'success' | 'gray' | 'destructive' | 'neutral' | null | undefinednone
size'md' | 'sm' | 'lg' | null | undefinednone

ToggleAnimated

ToggleAnimatedProps

animated

State

PropTypeDefault
checkedboolean | undefinednone
defaultCheckedboolean | undefinednone
onCheckedChange((checked: boolean) => void) | undefinednone

Behavior

PropTypeDefault
animationToggleAnimation | undefinednone
appearance'default' | 'blue' | 'cyan' | 'green' | 'lime' | 'mint' | 'ocean' | 'sapphire' | 'lavender' | 'ruby' | 'red' | 'slate' | 'zinc' | 'stone' | 'royal' | 'electric' | 'forest' | 'sunset' | 'magenta' | 'crimson' | 'aqua' | 'plum' | 'rose' | 'purple' | 'pink' | 'orange' | 'yellow' | 'teal' | 'indigo' | 'emerald' | 'gradient-blue' | 'gradient-green' | 'gradient-red' | 'gradient-yellow' | 'gradient-purple' | 'gradient-teal' | 'gradient-indigo' | 'gradient-pink' | 'gradient-orange' | 'success' | 'gray' | 'destructive' | 'neutral' | null | undefinednone
size'md' | 'sm' | 'lg' | null | undefinednone
thumbColor'default' | 'blue' | 'cyan' | 'green' | 'lime' | 'mint' | 'ocean' | 'sapphire' | 'lavender' | 'ruby' | 'red' | 'slate' | 'zinc' | 'stone' | 'royal' | 'electric' | 'forest' | 'sunset' | 'magenta' | 'crimson' | 'aqua' | 'plum' | 'rose' | 'purple' | 'pink' | 'orange' | 'yellow' | 'teal' | 'indigo' | 'emerald' | 'gradient-blue' | 'gradient-green' | 'gradient-red' | 'gradient-yellow' | 'gradient-purple' | 'gradient-teal' | 'gradient-indigo' | 'gradient-pink' | 'gradient-orange' | 'success' | 'gray' | 'destructive' | 'neutral' | null | undefinednone

Content

PropTypeDefault
childrenReactNodenone
Inherited HTML props
PropTypeDefault
classNamestring | undefinednone
idstring | undefinednone
onClickMouseEventHandler<HTMLButtonElement> | undefinednone
styleCSSProperties | undefinednone
titlestring | undefinednone
CSS variable overrides

Toggle CSS variables

Override these toggle variables on :root, a theme selector, or a component wrapper.

288 variables

Pattern: --zui-<component>-<slot?>-<variant?>-<property>-<state?>-dark?

:root {
  --zui-toggle-track-border: #0000001a;
  --zui-toggle-track-ring-focus: oklch(44.6% 0.043 257.281);
  --zui-toggle-track-ring-offset-focus: oklch(98.4% 0.003 247.858);
  --zui-toggle-track-border-checked: oklch(71.5% 0.143 215.221 / 0.4);
  --zui-toggle-track-default-bg-checked: oklch(78.9% 0.154 211.53 / 0.7);
  --zui-toggle-track-success-border-checked: oklch(69.6% 0.17 162.48 / 0.7);
  --zui-toggle-track-success-bg-checked: oklch(76.5% 0.177 163.223 / 0.8);
  --zui-toggle-track-destructive-border-checked: oklch(64.5% 0.246 16.439 / 0.4);
  --zui-toggle-track-destructive-bg-checked: oklch(71.2% 0.194 13.428 / 0.8);
  --zui-toggle-track-neutral-border-checked: oklch(55.4% 0.046 257.417 / 0.4);
  --zui-toggle-track-neutral-bg-checked: oklch(70.4% 0.04 256.788 / 0.9);
  --zui-toggle-track-indigo-border-checked: oklch(58.5% 0.233 277.117 / 0.4);
  --zui-toggle-track-indigo-bg-checked: oklch(67.3% 0.182 276.935 / 0.8);
  --zui-toggle-track-purple-border-checked: oklch(62.7% 0.265 303.9 / 0.4);
  --zui-toggle-track-purple-bg-checked: oklch(71.4% 0.203 305.504 / 0.8);
  --zui-toggle-track-pink-border-checked: oklch(65.6% 0.241 354.308 / 0.4);
  --zui-toggle-track-pink-bg-checked: oklch(71.8% 0.202 349.761 / 0.8);
  --zui-toggle-track-orange-border-checked: oklch(70.5% 0.213 47.604 / 0.4);
  --zui-toggle-track-orange-bg-checked: oklch(75% 0.183 55.934 / 0.8);
  --zui-toggle-track-yellow-border-checked: oklch(79.5% 0.184 86.047 / 0.4);
  --zui-toggle-track-yellow-bg-checked: oklch(85.2% 0.199 91.936 / 0.8);
  --zui-toggle-track-green-border-checked: oklch(72.3% 0.219 149.579 / 0.4);
  --zui-toggle-track-green-bg-checked: oklch(79.2% 0.209 151.711 / 0.8);
  --zui-toggle-track-teal-border-checked: oklch(70.4% 0.14 182.503 / 0.4);
  --zui-toggle-track-teal-bg-checked: oklch(77.7% 0.152 181.912 / 0.8);
  --zui-toggle-track-cyan-border-checked: oklch(71.5% 0.143 215.221 / 0.4);
  --zui-toggle-track-cyan-bg-checked: oklch(78.9% 0.154 211.53 / 0.8);
  --zui-toggle-track-lime-border-checked: oklch(76.8% 0.233 130.85 / 0.4);
  --zui-toggle-track-lime-bg-checked: oklch(84.1% 0.238 128.85 / 0.8);
  --zui-toggle-track-emerald-border-checked: oklch(69.6% 0.17 162.48 / 0.4);
  --zui-toggle-track-emerald-bg-checked: oklch(76.5% 0.177 163.223 / 0.8);
  --zui-toggle-track-rose-border-checked: oklch(64.5% 0.246 16.439 / 0.4);
  --zui-toggle-track-rose-bg-checked: oklch(71.2% 0.194 13.428 / 0.8);
  --zui-toggle-track-slate-border-checked: oklch(55.4% 0.046 257.417 / 0.4);
  --zui-toggle-track-slate-bg-checked: oklch(70.4% 0.04 256.788 / 0.9);
  --zui-toggle-track-zinc-border-checked: oklch(70.5% 0.015 286.067 / 0.4);
  --zui-toggle-track-zinc-bg-checked: oklch(44.2% 0.017 285.786 / 0.9);
  --zui-toggle-track-gray-border-checked: oklch(70.7% 0.022 261.325 / 0.4);
  --zui-toggle-track-gray-bg-checked: oklch(70.7% 0.022 261.325 / 0.8);
  --zui-toggle-track-stone-bg: oklch(86.9% 0.005 56.366);
  --zui-toggle-track-stone-border-checked: oklch(70.9% 0.01 56.259 / 0.4);
  --zui-toggle-track-stone-bg-checked: oklch(44.4% 0.011 73.639 / 0.9);
  --zui-toggle-track-gradient-blue-bg: oklch(80.9% 0.105 251.813);
  --zui-toggle-track-gradient-blue-from: oklch(42.4% 0.199 265.638);
  --zui-toggle-track-gradient-blue-to: oklch(43.8% 0.218 303.724);
  --zui-toggle-track-gradient-green-bg: oklch(87.1% 0.15 154.449);
  --zui-toggle-track-gradient-green-from: oklch(44.8% 0.119 151.328);
  --zui-toggle-track-gradient-green-to: oklch(45.3% 0.124 130.933);
  --zui-toggle-track-gradient-red-bg: oklch(80.8% 0.114 19.571);
  --zui-toggle-track-gradient-red-from: oklch(44.4% 0.177 26.899);
  --zui-toggle-track-gradient-red-to: oklch(45.9% 0.187 3.815);
  --zui-toggle-track-gradient-yellow-bg: oklch(90.5% 0.182 98.111);
  --zui-toggle-track-gradient-yellow-from: oklch(47.6% 0.114 61.907);
  --zui-toggle-track-gradient-yellow-to: oklch(47% 0.157 37.304);
  --zui-toggle-track-gradient-purple-bg: oklch(82.7% 0.119 306.383);
  --zui-toggle-track-gradient-purple-from: oklch(43.8% 0.218 303.724);
  --zui-toggle-track-gradient-purple-to: oklch(45.9% 0.187 3.815);
  --zui-toggle-track-gradient-teal-bg: oklch(85.5% 0.138 181.071);
  --zui-toggle-track-gradient-teal-from: oklch(43.7% 0.078 188.216);
  --zui-toggle-track-gradient-teal-to: oklch(45% 0.085 224.283);
  --zui-toggle-track-gradient-indigo-bg: oklch(78.5% 0.115 274.713);
  --zui-toggle-track-gradient-indigo-from: oklch(39.8% 0.195 277.366);
  --zui-toggle-track-gradient-indigo-to: oklch(43.8% 0.218 303.724);
  --zui-toggle-track-gradient-pink-bg: oklch(82.3% 0.12 346.018);
  --zui-toggle-track-gradient-pink-from: oklch(45.9% 0.187 3.815);
  --zui-toggle-track-gradient-pink-to: oklch(45.5% 0.188 13.697);
  --zui-toggle-track-gradient-orange-bg: oklch(83.7% 0.128 66.29);
  --zui-toggle-track-gradient-orange-from: oklch(47% 0.157 37.304);
  --zui-toggle-track-gradient-orange-to: oklch(44.4% 0.177 26.899);
  --zui-toggle-track-blue-border-checked: #2563eb66;
  --zui-toggle-track-blue-bg-checked: #2563ebcc;
  --zui-toggle-track-mint-border-checked: #10b98166;
  --zui-toggle-track-mint-bg-checked: #10b981cc;
  --zui-toggle-track-ocean-border-checked: #0284c766;
  --zui-toggle-track-ocean-bg-checked: #0284c7cc;
  --zui-toggle-track-sapphire-border-checked: #1d4ed866;
  --zui-toggle-track-sapphire-bg-checked: #1d4ed8cc;
  --zui-toggle-track-lavender-border-checked: #8b5cf666;
  --zui-toggle-track-lavender-bg-checked: #8b5cf6cc;
  --zui-toggle-track-ruby-border-checked: #be123c66;
  --zui-toggle-track-ruby-bg-checked: #be123ccc;
  --zui-toggle-track-red-border-checked: #dc262666;
  --zui-toggle-track-red-bg-checked: #dc2626cc;
  --zui-toggle-track-royal-border-checked: #4338ca66;
  --zui-toggle-track-royal-bg-checked: #4338cacc;
  --zui-toggle-track-electric-border-checked: #0ea5e966;
  --zui-toggle-track-electric-bg-checked: #0ea5e9cc;
  --zui-toggle-track-forest-border-checked: #16653466;
  --zui-toggle-track-forest-bg-checked: #166534cc;
  --zui-toggle-track-sunset-border-checked: #ea580c66;
  --zui-toggle-track-sunset-bg-checked: #ea580ccc;
  --zui-toggle-track-magenta-border-checked: #c026d366;
  --zui-toggle-track-magenta-bg-checked: #c026d3cc;
  --zui-toggle-track-crimson-border-checked: #b91c1c66;
  --zui-toggle-track-crimson-bg-checked: #b91c1ccc;
  --zui-toggle-track-aqua-border-checked: #0f766e66;
  --zui-toggle-track-aqua-bg-checked: #0f766ecc;
  --zui-toggle-track-plum-border-checked: #7e22ce66;
  --zui-toggle-track-plum-bg-checked: #7e22cecc;
  --zui-toggle-thumb-border: oklch(20.8% 0.042 265.755 / 0.3);
  --zui-toggle-thumb-shadow: 0 1px 2px rgba(15,23,42,0.12);
  --zui-toggle-thumb-colors-default-bg: #ffffff;
  --zui-toggle-thumb-colors-success-bg: oklch(69.6% 0.17 162.48);
  --zui-toggle-thumb-colors-destructive-bg: oklch(64.5% 0.246 16.439);
  --zui-toggle-thumb-colors-neutral-bg: oklch(55.4% 0.046 257.417);
  --zui-toggle-thumb-colors-indigo-bg: oklch(58.5% 0.233 277.117);
  --zui-toggle-thumb-colors-purple-bg: oklch(62.7% 0.265 303.9);
  --zui-toggle-thumb-colors-pink-bg: oklch(65.6% 0.241 354.308);
  --zui-toggle-thumb-colors-orange-bg: oklch(70.5% 0.213 47.604);
  --zui-toggle-thumb-colors-yellow-bg: oklch(79.5% 0.184 86.047);
  --zui-toggle-thumb-colors-green-bg: oklch(72.3% 0.219 149.579);
  --zui-toggle-thumb-colors-teal-bg: oklch(70.4% 0.14 182.503);
  --zui-toggle-thumb-colors-cyan-bg: oklch(71.5% 0.143 215.221);
  --zui-toggle-thumb-colors-lime-bg: oklch(76.8% 0.233 130.85);
  --zui-toggle-thumb-colors-emerald-bg: oklch(69.6% 0.17 162.48);
  --zui-toggle-thumb-colors-rose-bg: oklch(64.5% 0.246 16.439);
  --zui-toggle-thumb-colors-slate-bg: oklch(55.4% 0.046 257.417);
  --zui-toggle-thumb-colors-zinc-bg: oklch(55.2% 0.016 285.938);
  --zui-toggle-thumb-colors-gray-bg: oklch(55.1% 0.027 264.364);
  --zui-toggle-thumb-colors-stone-bg: oklch(55.3% 0.013 58.071);
  --zui-toggle-thumb-colors-gradient-blue-bg: oklch(62.3% 0.214 259.815);
  --zui-toggle-thumb-colors-gradient-green-bg: oklch(72.3% 0.219 149.579);
  --zui-toggle-thumb-colors-gradient-red-bg: oklch(63.7% 0.237 25.331);
  --zui-toggle-thumb-colors-gradient-yellow-bg: oklch(79.5% 0.184 86.047);
  --zui-toggle-thumb-colors-gradient-purple-bg: oklch(62.7% 0.265 303.9);
  --zui-toggle-thumb-colors-gradient-teal-bg: oklch(70.4% 0.14 182.503);
  --zui-toggle-thumb-colors-gradient-indigo-bg: oklch(58.5% 0.233 277.117);
  --zui-toggle-thumb-colors-gradient-pink-bg: oklch(65.6% 0.241 354.308);
  --zui-toggle-thumb-colors-gradient-orange-bg: oklch(70.5% 0.213 47.604);
  --zui-toggle-thumb-colors-blue-bg: #2563eb;
  --zui-toggle-thumb-colors-mint-bg: #10b981;
  --zui-toggle-thumb-colors-ocean-bg: #0284c7;
  --zui-toggle-thumb-colors-sapphire-bg: #1d4ed8;
  --zui-toggle-thumb-colors-lavender-bg: #8b5cf6;
  --zui-toggle-thumb-colors-ruby-bg: #be123c;
  --zui-toggle-thumb-colors-red-bg: #dc2626;
  --zui-toggle-thumb-colors-royal-bg: #4338ca;
  --zui-toggle-thumb-colors-electric-bg: #0ea5e9;
  --zui-toggle-thumb-colors-forest-bg: #166534;
  --zui-toggle-thumb-colors-sunset-bg: #ea580c;
  --zui-toggle-thumb-colors-magenta-bg: #c026d3;
  --zui-toggle-thumb-colors-crimson-bg: #b91c1c;
  --zui-toggle-thumb-colors-aqua-bg: #0f766e;
  --zui-toggle-thumb-colors-plum-bg: #7e22ce;
}

/* Dark theme variables follow the same names with -dark appended. */
.dark {
  --zui-toggle-track-border-dark: #ffffff1a;
  --zui-toggle-track-ring-focus-dark: oklch(86.9% 0.022 252.894);
}

What it does

Expose role=switch semantics and synchronize aria-checked with visual state.

Avoid using toggles for non-binary choices.

Composition and API

Prefer compound subcomponents instead of one oversized prop bag. Export a small, documented API for your design system.

Provide visible labels; do not rely on color alone for on/off meaning.

Common use cases

  • Feature flags for beta capabilities.
  • Notification preferences with instant feedback.
  • Compact filters on mobile toolbars.
  • Dark mode switches paired with system sync copy.

Accessibility

Keyboard order, focus rings, and ARIA attributes should match production usage. Test with your supported browsers and assistive technologies when semantics are non-trivial.

This preview page exposes a single h1 in the hero for a clean outline.

Next.js integration notes

Colocate examples under the App Router, keep server and client boundaries explicit, and avoid pulling interactive overlays into unexpected server layouts.

Set NEXT_PUBLIC_SITE_URL so canonical and Open Graph URLs resolve on deploy.

FAQ

Does the Toggle component work with Next.js App Router?

Yes. Import it like any other React component; keep interactive subtrees in client components when you need hooks or browser APIs, and leave static structure in server components where possible.

Can I customize toggle with Tailwind CSS?

Zentauri UI exposes class-friendly variants and slots so you can extend styles with Tailwind utilities without fighting inline styles.

Is this Toggle implementation accessible by default?

Primitives follow sensible defaults, but accessibility depends on how you label controls, manage focus, and wire keyboard handlers in your app. Validate critical flows with keyboard-only use and screen readers.