Switch
Turns a setting on or off immediately. Use it where the change takes effect the moment it is made.
import { Switch } from 'neba';
<Switch label="Email alerts" defaultChecked />;Props
| Prop | Type | Default | Description |
|---|---|---|---|
| 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 |
| label | ReactNode | — | The label, wired to the control by Base UI's Field |
| description | ReactNode | — | Helper text |
| error | ReactNode | — | Error message. Its presence turns the control invalid and re-points the colour family at danger |
| invalid | boolean | !!error | Forces the invalid state without a message, for when a form library owns validity |
| checked | boolean | — | Whether it is on. Use with onCheckedChange for a controlled switch |
| defaultChecked | boolean | false | The initial state, for an uncontrolled switch |
| onCheckedChange | (checked: boolean, details) => void | — | Called 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 |
| name | string | — | Identifies the field when a form is submitted |
| readOnly | boolean | false | Shown but not changeable. Keeps its colour and edge, drains the saturation |
| disabled | boolean | false | Unavailable. Drops the colour family for neutral grey |
| classNames | NebaSlots<'label' | 'control' | 'description' | 'error' | 'thumb'> | — | Class names for the parts behind the root. The root itself is className, so there is no root key |
If there is a Save button underneath and the value is submitted with a form, use Checkbox instead. That is what separates the two.
Examples
checked and onCheckedChange
checked with onCheckedChange makes it controlled; defaultChecked makes it uncontrolled.
disabled · readOnly
labelPlacement
end (the default) puts the label after the control, so it reads as a caption. start suits a settings list, where the labels form a left column and the switches line up on the right.
size
classNames
className lands on the field wrapper, not on the track. The track and the thumb are reached through classNames.
<Switch label="Email alerts" classNames={{ control: 'w-14', thumb: 'rounded-sm' }} />The slots are label, control, thumb, description and error. control is the track (the pill that fills when the switch is on), and thumb is the disc that travels across it. See prop conventions for how a class name you pass resolves against the component's own.
Accessibility
- Renders
role="switch"with a hidden<input>beside it. - The label is wired to the control, so clicking the text flips it.
- Without a
label, give it anaria-label. - The thumb's travel becomes instant under
prefers-reduced-motion.