Switch
A control that lets the user toggle between checked and not checked.
Installation
Install the following dependencies:
Set up the token layer and the StyleX compiler, if you have not already. See
Installation, and paste states.ts and
state-styles.ts from the same page. The switch imports both. The examples
caption their switches with a Label or a
Field.
Paste field-state.ts from the same installation page.
Copy and paste the following code into your project.
Update the import paths to match your project setup.
Usage
Match the label's htmlFor to the switch's id, or wrap the switch in the
label. A switch takes effect the moment it is flipped, so it needs no submit
button beside it. Use a Checkbox for a value that
is saved with a form.
The thumb travels on inset-inline-start, so it moves toward the inline end in
a right-to-left document.
Checked state
Use defaultChecked for an uncontrolled switch, or checked and
onCheckedChange to control it.
Give the switch a name to submit it with a form. Base UI renders a hidden
<input type="checkbox"> beside the control, and that input carries the value.
Description
Put the switch in a horizontal Field and a FieldContent beside it to add a
line of helper text under the label.
Focus is shared across devices, and turns off when you leave the app.
Choice card
Wrap a whole Field in a FieldLabel to turn the row into a card, and pass
checked to style the cards that are on.
FieldLabel does not read the switch's state, so checked is a prop you set from
the same value you give the switch. That makes the card a controlled switch.
Disabled
Set disabled on Field to disable its control and dim its label, or on a bare control directly.
Invalid
Set invalid on Field to style its control, or aria-invalid on a bare control. The examples show both.
Size
Use the size prop to change the size of the switch. The thumb and the travel
follow the track, so a sm switch needs no other change.
API reference
Pass render to replace a part's element or compose it with another component.
Switch wraps the Base UI Switch primitive and accepts its props. See the
Base UI reference.
Switch
| Prop | Type | Default |
|---|---|---|
size | "sm" | "default" | "default" |
checked | boolean | — |
defaultChecked | boolean | false |
onCheckedChange | (checked, details) => void | — |
name | string | — |
value | string | — |
disabled | boolean | false |
readOnly | boolean | false |
required | boolean | false |
aria-invalid | boolean | — |
id | string | — |
inputRef | Ref<HTMLInputElement> | — |
xstyle | StyleXStyles | — |
style | CSSProperties | — |
className | string | — |
The root is a <button role="switch">. Base UI renders a hidden <input>
beside it that carries id, name and value. A label's htmlFor and a
form submission reach the control through that input. The component renders the thumb.
There is no SwitchThumb part to place.
switchStyles
The style maps behind the component. Spread them onto any element.
| Key | What it is |
|---|---|
root | The track: shape, fill, hit area |
sizes | The sm and default track sizes, keyed by name |
checked | The primary fill and its sheen |
disabled | The dimmed, non-interactive state |
invalid | The destructive border and ring |
thumb | The thumb at rest and the transition it travels on |
thumbChecked | The thumb's far end of the travel and its fill |
A size sets --carbon-switch-thumb, which the thumb reads for its width,
height and the distance it moves. Override that property to resize a switch
without adding a size.
root carries no focus ring. The ring, disabled and invalid all come from
states in theme/states.ts, and the ring reads a resting border colour from
--carbon-border-color. The switch leaves that property unset, so the track's
border stays transparent until focus colours it.
Data attributes
| Attribute | On | Effect |
|---|---|---|
data-slot="switch" | the track | Targets the control |
data-slot="switch-thumb" | the thumb | Targets the moving part |
data-size | the track | Mirrors the size prop |
data-checked, data-unchecked | track, thumb | Base UI writes them |
data-disabled, data-readonly, data-required | track, thumb | Base UI writes them |