Switch
$ npx shadcn@latest add https://lacodda.github.io/dowel/r/switch.jsonThe difference from Checkbox is not how it looks, and getting it wrong is the commonest mistake in the pair. A checkbox is an answer collected now and submitted later, with the rest of the form. A switch is a setting that applies the moment it moves.
If there is a Save button, it is a Checkbox. If the change is the action, it is a Switch.
Put a switch in a form behind a Save button and the reader cannot tell whether anything happened: they flipped it, and nothing said so.
<Switch defaultChecked>Notify me</Switch>It reports its state, not only its position. The role is switch and
aria-checked follows it — which matters more than it looks, because under
reduced motion the theme drops the slide and the position is all that changes
on screen.
The track carries the accent when on, and it is the only colour in the control, so a column of settings reads as a list of on-and-off rather than a field of decoration.
A switch with no words is a light with no caption. Leave them out only where the meaning is genuinely in the context, and then name it:
<Switch aria-label="Notify me" />Props
Read from the types in ui/switch.tsx, the file a product copies - so the description of each prop is also what an editor shows over it there.
| Prop | Type | Default | |
|---|---|---|---|
children | ReactNode | The words next to the switch. A switch with no label is a light with no caption - give aria-label if the meaning is genuinely in the context. | |
checked | boolean | Whether the switch is on, when the caller owns the state. Pair it with onCheckedChange. | |
defaultChecked | boolean | Whether the switch starts on, when it manages its own state. | |
onCheckedChange | (checked: boolean) => void | Told the new state when the switch is flipped. | |
disabled | boolean | The switch cannot be flipped; it and its label dim. | |
required | boolean | Marks the switch as required for a form. | |
readOnly | boolean | The state shows but cannot be changed by the reader. | |
name | string | The field name submitted with a form. | |
aria-label | string | Names the switch for a screen reader when it has no children. | |
className | string |
Accessibility
The examples on the stand, through axe 4.14.0 in a browser, in both themes, against WCAG 2.2 A and AA and axe's best practices: 18 rules applied and passed, and none failed. The accessibility report has every item.
History
Each release that changed ui/switch.tsx - the file a product copies - newest first.