Skip to content
Folio

Forms

Switch

A setting that takes effect immediately.

Usage

When to reach for it

Inside a form with a Save button, a switch is a lie about when the change happened. Use a Checkbox.
TSX
import { Switch } from '@misoto22/design'

Notes

A setting that takes effect immediately.

Distinct from Checkbox, and the distinction is not cosmetic: a switch applies on flip, a checkbox applies on submit. A switch inside a form with a Save button is a lie about when the change happened.

The track fills with ink when on and the thumb is paper with a hairline — rather than a white thumb floating on a drop shadow, which this system does not have. The off state is a filled rule-coloured track, so the control still reads as a control on a white page.

Anatomy

Switch anatomy
ElementDescription
TrackrequiredA 36×20 <button role="switch"> on a pill radius, filled --stone when off and --accent when on. Filled rather than outlined, so it still reads as a control on a white page.
ThumbrequiredA 14px paper circle with a hairline, not a white disc on a shadow — this system has no shadows. It stretches to 20px while pressed and rounds out as it lands; motion-reduce drops that entirely.
LabelNot rendered here either. The Radix root IS a <button>, though, which a <label for> does bind to — so unlike Select or RadioGroup, a Field’s label above a Switch really does click through to it.

Best practices

Do

  • Handle the failure at the control. The flip has already claimed the change happened, so an onCheckedChange whose request fails must put the thumb back and say why, or the page is showing a setting the server does not have.
  • Name it for the state, not the action: the accessible name is read together with “on” or “off”, so “Email notifications, on” is a sentence and “Turn on email notifications, on” is two contradictory ones.
  • Keep the flip instant to the eye even when the write is not — an optimistic thumb with a quiet undo beats a spinner on a control whose whole claim is that it already took effect.

Don’t

  • A switch has two states and no third. “Inherit from the workspace” cannot be a switch, because the only way to draw it is unchecked, which announces “off” — that is a RadioGroup or a Select.
  • There is no readOnly: disabled is the only lock, and it takes the control out of the tab order, so a keyboard reader tabbing the form passes the setting without ever hearing its value.
  • Do not add transition-all from a call site. It replaces transition-[transform,width] wholesale, which puts the track’s colour on the thumb’s longer duration and turns a flip into a fade.

Examples

default

Two settings that take effect on the flip rather than on a save — which is the whole line between this and Checkbox, and not a cosmetic one: a switch inside a form with a Save button is a lie about when the change happened. Both are named for the state and not for the action, because the name is read together with “on” or “off”: “Email notifications, on” is a sentence, and “Turn on email notifications, on” is two contradictory ones. The Radix root is a button, which a label does bind to, so unlike Select or RadioGroup a Field's label above a Switch really does click through.

a failed write

The flip has already claimed the change happened, so a write that fails has to be handled at the control: put the thumb back, and say why. Turn this one on — the request behind it fails a moment later, the switch returns to off and the reason appears beneath it. A switch left on over a write that never landed is a page showing a setting the server does not have. Keep the flip itself instant even when the write is not: an optimistic thumb with a quiet undo beats a spinner on a control whose whole claim is that it already took effect.

a third state

A switch has two states and no third. “Inherit from the workspace” has no drawing on a track: the only thing it could be is unchecked, which announces itself as off — a different answer to a different question. On the left, a setting that really is on or off; on the right, the same setting once a third value exists, which is a RadioGroup and not a switch someone has been clever with.

Two states

Three

Keyboard

Switch keyboard interactions
KeyDoes
SpaceEnterToggles it, and the change applies immediately.