Switch
A headless, accessible switch for toggling a single on/off value with full keyboard and native form support.
Features
- Headless switch primitive
- Controlled or uncontrolled
- Keyboard accessible
- Native form integration
- Disabled state support
- Composable parts and state data
Installation
npm install @ariaui/switch
Examples
Three playgrounds: uncontrolled rows (including a disabled switch), a controlled "Remember me" field, and a compact disabled airplane-mode row.
Shared track and thumb classes live in switchExampleTokens.ts; compose Root, Track (WAI-ARIA role="switch"), and Thumb for keyboard support.
Uncontrolled
Use defaultChecked for an initial value; the row stays copy-pasteable without extra React state.
No preview output yet.
Controlled
Drive the checked state from React and pass onCheckedChange to keep the UI in sync.
No preview output yet.
Disabled
Set disabled on the root to lock the switch and remove it from the tab order.
No preview output yet.
Framer Motion
Use Thumb asChild to slot switch state onto a Framer Motion thumb.
No preview output yet.
Anatomy
import * as Switch from "@ariaui/switch";
export default function Example() {
return (
<Switch.Root>
<Switch.Track>
<Switch.Thumb />
</Switch.Track>
</Switch.Root>
);
}
API Reference
Root
Container that owns the checked state and renders a hidden `<input type="checkbox">` for native form integration.
| Prop | Type | Default |
|---|---|---|
checked | boolean | — |
defaultChecked | boolean | false |
onCheckedChange | (checked: boolean) => void | — |
disabled | boolean | false |
Track
Focusable visual track that carries switch semantics. Pass `aria-label` or `aria-labelledby` here so the switch has an accessible name.
| Prop | Type | Default |
|---|---|---|
disabled | boolean | — |
| Attribute | Values |
|---|---|
| role | 'switch' |
| aria-checked | 'true' | 'false' |
| aria-disabled | present when disabled |
Thumb
Visual sliding indicator. Reads state from context — no interaction logic of its own.
| Prop | Type | Default |
|---|---|---|
asChild | boolean | false |
| Attribute | Values |
|---|---|
| data-state | 'checked' | 'unchecked' |
| data-disabled | present when disabled |
Keyboard
| Shortcut | Action |
|---|---|
| Space | Toggle the switch between checked and unchecked. |
| Tab | Move focus to the Track. |
| Shift+Tab | Move focus to the previous focusable element. |
Accessibility
Switch follows the WAI-ARIA Switch pattern:
Trackcarriesrole="switch"witharia-checkedtoggling between"true"and"false"— screen readers announce it as a switch, not a checkbox.- Always give Switch a visible label or
aria-label. Without one, assistive tech only announces "switch on" / "switch off" with no context of what it controls. The simplest pattern is a<label htmlFor>paired with the Root'sid. Rootrenders a hidden<input type="checkbox">soname,value,required, and native form submission all work without extra plumbing.- When
disabledis set, Track receivesaria-disabledand drops out of the tab order (tabindex="-1"), and every part gainsdata-disabledfor styling. - Space on a focused Track toggles checked state; Tab and Shift+Tab move focus in and out of the switch.