Components

Switch

A React switch with a Liquid Glass thumb, label, description, and monochrome theme.

Switch renders a two-state control with a Liquid Glass track and thumb. Use it for settings that take effect immediately; for a single action that stays pressed, use Toggle.

Basic example

The switch below is the real component and can be clicked directly.

Receive notificationsWhen enabled, new messages are sent to your inbox.

The switch root is the outermost element. The visual track is the inner base slot, and the whole row, including the label and description, is clickable. label becomes the accessible name through aria-labelledby; when the control has a label or explicit name, description is linked through aria-describedby. An explicit aria-label or aria-labelledby takes precedence for the name, and an explicit aria-describedby is merged with the description. A description-only control uses the description as its name and does not add aria-describedby.

Sizes

Supports xs / sm / md / lg / xl, defaulting to md. The track and text scale together with the size.

XSSMMDLGXL

Controlled usage

checked and onCheckedChange let external state fully control the switch:

Receive notificationsNew messages will be sent to your inbox.

Uncontrolled usage

Without checked, Switch owns its state, and defaultChecked only sets the initial value:

Enable notificationsNew messages will be sent to your inbox.

Form usage

Switch forwards name and value and submits the current value through a hidden checkbox input:

Receive notificationsWhen enabled, new messages are sent to your inbox.

Not submitted yet

Disabled and read-only

DisabledRead-only

Accessibility

Switch renders a focusable element with role="switch" and aria-checked (a <span> by default). The visible label names it and description is linked with aria-describedby; explicit ARIA names take precedence.

Space toggles the focused control. The hidden checkbox carries name and value for form submission, and readOnly prevents changes while keeping focus. See the accessibility guide for form patterns.

API reference

PropTypeDefaultDescription
labelReactNode—Visible label. It becomes the accessible name unless aria-label or aria-labelledby is provided.
descriptionReactNode—Supporting text, linked with aria-describedby when the control has a name.
size"xs" | "sm" | "md" | "lg" | "xl""md"Controls track size and text size.
checkedboolean—Controlled checked state.
defaultCheckedbooleanfalseInitial checked state when uncontrolled.
onCheckedChange(checked: boolean, details) => void—Called when the checked state changes.
disabledbooleanfalseDisables the switch.
readOnlybooleanfalsePrevents toggling while remaining focusable.
requiredbooleanfalseRequires the switch to be on for form submission.
namestring—Form field name.
formstring—ID of the form that owns the hidden input.
valuestring—Value submitted with the form when the switch is on.
uncheckedValuestring—Value submitted with the form when the switch is off.
idstring—ID of the hidden input, or of the root element when nativeButton is true.
inputRefRef<HTMLInputElement>—Ref to the hidden native input.
nativeButtonbooleanfalseWhether the rendered element is a native <button>.
renderReactElement | ((props, state) => ReactElement)—Replaces the root element.
refRef<HTMLElement>—Ref forwarded to the root element.
classNamestring—Tailwind classes merged into the switch root.
styleCSSProperties—Inline styles merged into the same element as className.
ui{ root?: ClassValue; container?: ClassValue; base?: ClassValue; thumb?: ClassValue; wrapper?: ClassValue; label?: ClassValue; description?: ClassValue }—Tailwind classes for internal slots, keyed by data-slot.
AttributeDescription
data-checkedPresent when the switch is on.
data-uncheckedPresent when the switch is off.
data-disabledPresent when the switch is disabled.
data-readonlyPresent when the switch is read-only.
data-requiredPresent when the switch is required.
data-validPresent when the switch is valid and wrapped in Field.
data-invalidPresent when the switch is invalid and wrapped in Field.
data-touchedPresent after the switch is touched while wrapped in Field.
data-dirtyPresent after the switch value changes while wrapped in Field.
data-filledPresent when the switch is on while wrapped in Field.
data-focusedPresent when the switch is focused while wrapped in Field.
data-animatingPresent while the thumb transition is running.
data-slotMarks internal parts (root, container, base, thumb, wrapper, label, description) for styling.

Theming

The track and thumb use --ui-ink and --ui-surface. Component-specific geometry lives in src/theme/switch.ts as --ui-switch-width, --ui-switch-height, --ui-switch-inset, --ui-switch-thumb-size, and --ui-switch-travel. Override them with style on the Switch, use className for layout, and use ui for internal slots keyed by data-slot. See the theming guide for token layers and presets.

  • Checkbox — For choices that are confirmed with a form.
  • Radio Group — For one choice among several.
  • Toggle — For a button that stays pressed.