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.

Preview

No preview output yet.

live.tsxReady

Controlled

Drive the checked state from React and pass onCheckedChange to keep the UI in sync.

Preview

No preview output yet.

live.tsxReady

Disabled

Set disabled on the root to lock the switch and remove it from the tab order.

Preview

No preview output yet.

live.tsxReady

Framer Motion

Use Thumb asChild to slot switch state onto a Framer Motion thumb.

Preview

No preview output yet.

live.tsxReady

Anatomy

tsx
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.

PropTypeDefault
checked
boolean
defaultChecked
booleanfalse
onCheckedChange
(checked: boolean) => void
disabled
booleanfalse

Track

Focusable visual track that carries switch semantics. Pass `aria-label` or `aria-labelledby` here so the switch has an accessible name.

PropTypeDefault
disabled
boolean
AttributeValues
role'switch'
aria-checked'true' | 'false'
aria-disabledpresent when disabled

Thumb

Visual sliding indicator. Reads state from context — no interaction logic of its own.

PropTypeDefault
asChild
booleanfalse
AttributeValues
data-state'checked' | 'unchecked'
data-disabledpresent when disabled

Keyboard

ShortcutAction
SpaceToggle the switch between checked and unchecked.
TabMove focus to the Track.
Shift+TabMove focus to the previous focusable element.

Accessibility

Switch follows the WAI-ARIA Switch pattern:

  • Track carries role="switch" with aria-checked toggling 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's id.
  • Root renders a hidden <input type="checkbox"> so name, value, required, and native form submission all work without extra plumbing.
  • When disabled is set, Track receives aria-disabled and drops out of the tab order (tabindex="-1"), and every part gains data-disabled for styling.
  • Space on a focused Track toggles checked state; Tab and Shift+Tab move focus in and out of the switch.
Previous
Splitter
Next
Table