Switch
A toggle control for boolean settings. Uses role='switch' for accessibility and supports both controlled and uncontrolled patterns.
Preview
Alerts for new messages and mentions.
Sizes
| Size | Track | Thumb |
|---|---|---|
| sm | 28 × 16px | 12 × 12px |
| md | 36 × 20px | 14 × 14px |
| lg | 44 × 24px | 18 × 18px |
Motion
| Property | Value | Easing |
|---|---|---|
| thumb translate-x | ±(track width - thumb - 2×offset) | 200ms ease |
| thumb background | tertiary → white | 200ms ease |
| track background | surface-raised → accent | 200ms ease |
Implementation
Switch.tsx
tsx
import { Switch } from "@/components/ui/Switch";
import { useState } from "react";
// Uncontrolled
<Switch label="Dark mode" defaultChecked />
// Controlled
const [enabled, setEnabled] = useState(false);
<Switch
label="Enable notifications"
helperText="Push alerts for new messages and mentions."
checked={enabled}
onChange={(e) => setEnabled(e.target.checked)}
/>
// Disabled
<Switch label="Beta features" disabled defaultChecked />
<Switch label="Legacy mode" disabled />Props
All native <input type="checkbox"> attributes are forwarded. The switch renders as role="switch".
| Prop | Type | Default | Description |
|---|---|---|---|
label | string | — | Visible label rendered beside the switch track. |
helperText | string | — | Supplemental hint rendered below the label. |
size | "sm" | "md" | "lg" | "md" | Controls the track and thumb dimensions. |
checked | boolean | — | Controlled on/off state. |
defaultChecked | boolean | false | Initial state for uncontrolled usage. |
disabled | boolean | false | Prevents interaction and dims the control. |
onChange | (e: React.ChangeEvent<HTMLInputElement>) => void | — | Called when the switch changes state. |
ARIA roles
| Element | Role | Key attributes |
|---|---|---|
| Input | switch | aria-checked (true/false), aria-labelledby, aria-describedby |
Keyboard
| Key | Action |
|---|---|
| Space | Toggle the switch on or off |
| Tab | Move focus to the next focusable element |
| Shift+Tab | Move focus to the previous focusable element |
Accessibility
- →Uses role="switch" — screen readers announce the state as "on" or "off", not "checked" or "unchecked".
- →The underlying input is sr-only; the visual track and thumb are purely presentational.
- →Keyboard: Space toggles the switch when focused.
- →Focus ring appears via focus-visible — keyboard only.
- →Disabled state sets disabled on the input and visually dims the control.
- →Prefer Switch over Checkbox for settings that take immediate effect (dark mode, airplane mode). Use Checkbox for form fields that require explicit submission.