Skip to content

Switch

An immediate on/off. The difference from a Checkbox is not visual, it is temporal.

tsx
import { Switch } from 'neba';

<Switch label="Email alerts" defaultChecked />;

Props

PropTypeDefaultDescription
sizeshared'xs' | 'sm' | 'md' | 'lg' | 'xl''md'Height and type scale
colorshared'primary' | 'secondary' | 'success' | 'warning' | 'danger' | 'info''primary'Semantic colour role. Arbitrary colour values are not accepted
labelReactNodeThe label, wired to the control by Base UI's Field
descriptionReactNodeHelper text
errorReactNodeError message. Its presence turns the control invalid and re-points the colour family at danger
invalidboolean!!errorForces the invalid state without a message, for when a form library owns validity
checkedbooleanWhether it is on. Use with onCheckedChange for a controlled switch
defaultCheckedbooleanfalseThe initial state, for an uncontrolled switch
onCheckedChange(checked: boolean, details) => voidCalled when the switch is turned on or off
labelPlacement'start' | 'end''end'Which side the label sits on. `start` is for a settings list, where the switches line up on the right
namestringIdentifies the field when a form is submitted
readOnlybooleanfalseShown but not changeable. Keeps its colour and edge, drains the saturation
disabledbooleanfalseUnavailable. Drops the colour family for neutral grey

Switch or checkbox?

A checkbox is a value that gets submitted with a form. A switch takes effect the moment it moves. If there is a Save button underneath it, it should have been a checkbox.

Examples

States

Label placement

end reads as a caption for the control. start is for a settings list, where the labels form a column and every switch lines up on the right.

Sizes

The two rules it bends

It is a pill. Everywhere else the radius stops short of 50%, because the flat run along the top and bottom edge is what reads as a sheet with its corners cut off. A switch is not a sheet — it is a track something runs along, and a track with corners is a track the thumb would have to climb out of.

Something moves. This is the only component in the library where anything travels, and it travels on left, not on a transform. The no-transform rule exists because scaling a control resamples its label; the thumb carries no text, and its movement is the control. Under prefers-reduced-motion the travel drops to 0ms with everything else.

Accessibility

  • Renders a real role="switch" with a hidden <input> beside it.
  • The label is wired to the control by Base UI's Field: clicking the text flips it.
  • Without a label, give it an aria-label.

Released under the MIT License