Switch
How the Switch works with a keyboard and assistive tech, and where it stands against WCAG 2.2 AA.
The Switch is a <button role="switch"> with aria-checked, so it is announced as a switch that is on or off and flips with Space or Enter. Because it acts at once, it should only ever control something that takes effect immediately.
Keyboard#
Moves focus to the switch. A disabled or read-only switch is skipped.
Moves focus to the previous focusable element.
Turns the switch on or off.
Turns the switch on or off, as any button does.
Semantics#
<button role="switch">Native focus and keyboard, announced as a switch rather than a button.
Alwaysaria-checkedtrue when on, false when off, so the state is read, not inferred from colour.
Alwaysaria-labelledbyPoints at the title, so it is read as Dark mode, switch, on.
Label row and cardaria-labelA switch with no visible title needs a name passed in.
Switch alonearia-describedbyLinks the description, so it is read after the state.
descriptiondisabledRemoved from the tab order. Read-Only uses it too.
Disabled or Read-Onlyaria-hidden="true"The cross, tick and rings are drawing only.
Icon, ringsColour contrast#
Every variant and state has to meet WCAG 2.2 Level AA. Measure the colours as they land on screen: a translucent hover or press wash over whatever sits behind it.
Off track · Off
The #f2f2f2 track is 1.12:1 on white. An off switch is shown only by the thumb's shadow, well under 3:1.
WCAG 1.4.11 Non-text Contrast ↗On track · On
Grey #2a2a2a and Brand #005cf8 against the page, and the white thumb against them, all pass.
WCAG 1.4.11 Non-text Contrast ↗State not by colour · All
The thumb's position shows the state as well as the colour, and aria-checked gives it to assistive tech. The optional cross and tick add one more signal.
WCAG 1.4.1 Use of Color ↗WCAG 4.1.2 Name, Role, Value ↗Label and description · Label row, Card
The title in #2a2a2a and the sub-label and description in #6d6d6d pass on white and on the card's 4% hover wash.
WCAG 1.4.3 Contrast (Minimum) ↗Focus indicator · Focus visible
A 2px ring in #1a6ef8 off a white gap, on keyboard focus only. It measures 4.54:1 on white, so it clears 3:1 on every light surface the library uses.
WCAG 1.4.11 Non-text Contrast ↗WCAG 2.4.13 Focus Appearance ↗Disabled · Disabled
Inactive controls are exempt. The disabled text and glyphs (#cbcbcb) are deliberately faint.
WCAG 1.4.3 Contrast (Minimum) ↗Measured contrast#
The track against a white page, and the optional cross or tick against the white thumb, from the ds.css tokens; every row is a graphic and is held to 3:1. 8 of 16 pairs fall below their minimum (4.5:1 for text, 3:1 for graphics) and are marked in amber.
Motion#
- The thumb slides over 200ms and the track changes colour over 180ms. Both are turned off under prefers-reduced-motion, and the switch changes at once.
- While pressed on, the thumb shrinks 2px. Under reduced motion it still shrinks, without the transition.
Checklist#
Use a switch only for a setting that applies the moment it changes. If it waits for Save, use a Checkbox.
The name says what is switched (Dark mode), never the state (On); aria-checked carries the state.
The off track (#f2f2f2, 1.12:1) is under the 3:1 non-text minimum. Use the rings, or add a darker edge, until the track is darkened.
The off-state cross is #cbcbcb on white (1.62:1); it adds little. The on-state tick passes.
Small (20px) and x-Small (16px) keep a 24px hit area around the track, which meets WCAG 2.5.8.
In the label row the title is not a <label>, so clicking it does not flip the switch. Make the row a label, or keep the switch itself large enough to hit.
Read-Only is drawn with disabled and leaves the tab order. Where the value matters, also state it in text.
