Forms & Controls
Switch
A two-state on/off toggle control, distinct from a checkbox semantically.
Last verified against WCAG 2.2 and WAI-ARIA APG 1.2 on 2026-07-02.
Implementation
Wi-Fi
switch-pattern.tsx
function SwitchPattern() {
const [on, setOn] = useState(true);
function toggle() { setOn(v => !v); }
return (
<button
type="button"
role="switch"
aria-checked={on}
aria-labelledby="wifi-switch-label"
onClick={toggle}
onKeyDown={e => {
if (e.key === " ") { e.preventDefault(); toggle(); }
}}
>
<span aria-hidden="true" className="thumb" />
</button>
);
}
/* role="switch" (not "checkbox") is what makes AT announce
"switch, on/off" — matching the instant-effect mental model a toggle
switch implies, vs. a checkbox that often implies "apply on submit." */Live demo
Wi-Fi
Required roles, states & properties
| Element | Attribute | Why |
|---|---|---|
| Switch <button> | role="switch" | Announced as "switch," distinct from role="checkbox" — communicates an instant on/off effect rather than a form value applied later. |
| Switch <button> | aria-checked | A strict boolean (true/false only — switches have no mixed state) reflecting on/off. Announced as "on"/"off" by most screen readers instead of "checked"/"not checked." |
| Switch <button> | aria-labelledby (or aria-label) | Gives the switch an accessible name, since the visible label text (e.g. "Wi-Fi") is a separate element, not the button's own text content. |
Keyboard interaction model
| Key | Behavior |
|---|---|
| Tab / Shift+Tab | Moves focus to/from the switch like any other control. |
| Space | Toggles the switch on/off. |
| Enter | Also toggles the switch — <button> fires onClick for both Enter and Space natively, so no extra handling is required. |
Focus management rules
- The switch is always a single Tab stop — there's no roving tabindex or sub-navigation involved.
- Toggling the switch never moves focus away from it, so users can flip several switches in a row with repeated Space presses.
- Changing a switch's state must never trigger an unexpected context change (e.g. navigating away or opening a dialog) per SC 3.2.2 On Input.
WCAG 2.2 success criteria mapping
| SC | Name | Level | Why it applies |
|---|---|---|---|
| 1.3.1 | Info and Relationships | A | Structure and relationships conveyed visually are also programmatically determinable. |
| 2.1.1 | Keyboard | A | All functionality is operable through a keyboard interface with no specific timing. |
| 2.5.8 | Target Size (Minimum) | AA | Pointer targets are at least 24x24 CSS pixels, unless spaced, inline, or essential. |
| 4.1.2 | Name, Role, Value | A | For all UI components, name, role, and value are programmatically determinable; states and changes are announced. |