Switch

Instant on/off toggle — native checkbox with role="switch" and a glass track. Control and label are vertically centered; add .items-start when the label wraps.

Preview

Live

<label class="switch">
  <input
    class="switch__input"
    type="checkbox"
    role="switch"
    name="auto"
    aria-checked="true"
    checked
  />
  <span class="switch__track" aria-hidden="true">
    <span class="switch__thumb"></span>
  </span>
  <span class="switch__label">Auto-apply matching roles</span>
</label>

Variants

On

Checked — blue track, thumb at the end.

Off

Unchecked glass track.

Invalid

.is-invalid for validation errors.

Disabled

Native disabled — no press.

Accessibility

  • Use role="switch" on the checkbox and keep aria-checked in sync with checked state.
  • Space / Enter toggle via the native checkbox; focus-visible ring lands on the track.
  • The track and thumb are decorative — aria-hidden="true" on the track.
  • Prefer a visible label; do not rely on color alone for on/off meaning.
  • Switches are for immediate settings — use a checkbox when the change needs an explicit submit.

API

HTML classes

Class Description
.switch Root label / wrapper.
.switch__input Native checkbox with role="switch".
.switch__track Glass pill track.
.switch__thumb Sliding knob inside the track.
.switch__label Visible label text.
.is-invalid Error border / ring on root or input.

React props

From src/core/Switch.tsx — extends native InputHTMLAttributes<HTMLInputElement> (minus type / role). Syncs aria-checked for controlled and uncontrolled usage.

Prop Type Default Description
invalid boolean false Applies .is-invalid and aria-invalid.
children ReactNode When set, wraps in a <label> with label text.
checked / defaultChecked boolean Controlled or uncontrolled on state.
onChange native Fires on toggle; uncontrolled state updates internally.
disabled boolean Native disabled state.
className string Merged onto the root wrapper.