5.9 KiB
Switch
(no submodules)
- switch.variants — `switchVariants` and `switchThumb…-
switch.variants —
switchVariantsandswitchThumbVariantsare the two cva (class-variance-authority) configurations that together powe… -
switch.variants —
switchVariantsand `switchThumb… -
switch.variants —
switchVariantsandswitchThumbVariantsare the two cva (class-variance-authority) configurations that together powe… -
switch.variants —
switchVariantsand `switchThumb… -
switch.variants —
switchVariantsandswitchThumbVariantsare the two cva (class-variance-authority) configurations that together powe… -
switch.variants —
switchVariantsand `switchThumb… -
switch.variants —
switchVariantsandswitchThumbVariantsare the two cva (class-variance-authority) configurations that together powe… -
switch.variants —
switchVariantsandswitchThumbVariantsare the two cva (class-variance-authority) configurations that together powe…
Purpose
<Switch> is the chassis on/off toggle primitive built on @radix-ui/react-switch. Radix supplies the a11y semantics (role="switch", aria-checked reflecting boolean state, native Space activation, disabled propagation); the chassis layers theme-driven variant resolution, the sliding-thumb render, and the cva size axis that scales both the track and the thumb proportionally.
The thumb cva is exported alongside the track cva so consumers can theme each independently. Refs are forwarded to the Radix Root which renders a styled <button>.
Icon-only switches (no visible label sibling) MUST supply an aria-label so screen readers can announce what is being toggled. The chassis does NOT inject a fallback because the label is domain-specific — only the consumer knows what is being switched on or off.
Features
- Three sizes (
sm,default,lg) scaling track + thumb proportionally. - Sliding thumb with
data-[state=checked]:translate-x-*driving the on/off motion via Tailwind transforms. - Controlled and uncontrolled use via Radix
checked/defaultChecked/onCheckedChange. disabledblocks pointer + keyboard input and decays opacity.data-state="checked|unchecked"mirrored on the rendered button.- Refs forwarded to the Radix Root.
motion-reduce:transition-nonecollapses both colour + transform transitions forprefers-reduced-motion: reduce.- Theme-driven variant overrides via
useThemedVariants("Switch", switchVariants).
Usage: Basic Example
import { Switch } from "@suaveplan/react-ui";
export function AirplaneToggle() {
return (
<div className="flex items-center gap-2">
<Switch id="airplane" />
<label htmlFor="airplane">Airplane mode</label>
</div>
);
}
Usage: Advanced Example
import { Switch } from "@suaveplan/react-ui";
import { useState } from "react";
export function NotificationSettings() {
const [enabled, setEnabled] = useState(true);
const [marketing, setMarketing] = useState(false);
return (
<div className="flex flex-col gap-3 p-4 border rounded">
<div className="flex items-center justify-between">
<label htmlFor="notif">Notifications</label>
<Switch
id="notif"
checked={enabled}
onCheckedChange={setEnabled}
/>
</div>
<div className="flex items-center justify-between">
<label htmlFor="marketing">Marketing emails</label>
<Switch
id="marketing"
checked={marketing}
disabled={!enabled}
onCheckedChange={setMarketing}
/>
</div>
</div>
);
}
API Reference
<Switch>
forwardRef<ComponentRef<typeof SwitchPrimitive.Root>, SwitchProps> — wraps Radix Root, renders a <button role="switch"> containing the sliding thumb.
SwitchProps
Inherits every prop from Radix SwitchPrimitive.Root except asChild. Adds:
| Prop | Type | Default | Description |
|---|---|---|---|
size |
"sm" | "default" | "lg" |
"default" |
Visual variant scaling track + thumb. |
Common Radix props consumers will use:
| Prop | Type | Default | Description |
|---|---|---|---|
checked |
boolean |
uncontrolled | Controlled state. |
defaultChecked |
boolean |
false |
Initial state for uncontrolled use. |
onCheckedChange |
(checked: boolean) => void |
none | Fires on state change. |
disabled |
boolean |
false |
Blocks input + decays opacity. |
required |
boolean |
false |
Native form-field required. |
name |
string |
none | Native form-field name. |
value |
string |
"on" |
Native form-field value when checked. |
switchVariants / switchThumbVariants
Both bare cva resolvers are exported so external consumers can re-use the variants directly.
Implementation Notes
- The track and thumb cva configs are kept separate so consumer themes can override either independently — for example a theme that makes the thumb glossy without changing the track shape.
- The thumb's
translate-x-*per-size value is hard-coded intoswitchThumbVariantsrather than computed because cva is a string-templating library, not a runtime calculator. The math istrack-width − thumb-width − padding-x*2. motion-reduce:transition-noneapplies to both the track (colour transition) and the thumb (transform transition) so reduced-motion users see instant state changes.- Refs target the Radix Root (the
<button>element) — consumers can.focus()the switch programmatically through the forwarded ref. - The chassis does NOT auto-inject an
aria-labelfor icon-only use — seePurpose.