Skip to contentAsheeUIAsheeUI

Switch

One boolean, applied the moment it is flipped.

A switch sets one boolean, and it takes effect immediately: there is no Save button beside it, which is what separates it from a checkbox. A checkbox is a value a form submits later; a switch is a setting that is now on or now off. That is why the label names the setting rather than asking a question, and why the description says what turning it on does, a switch is read at rest as often as it is flipped.

Usage

import { Switch } from "@asheeui/web";

<Switch label="Email notifications" defaultChecked />

Uncontrolled is enough while the setting is only read when the form is submitted. When the value has to live with the rest of the page, to enable another field, to save it as soon as it changes, drive it with checked and onChange:

<Switch
  label="Email notifications"
  description="We tell you when an invoice is paid."
  checked={notifications}
  onChange={setNotifications}
/>

States

The track fills with the accent once the switch is on, and the knob travels from one end to the other; both follow size, and the accent follows color. The track and the knob keep their size in every state, so nothing in the row moves when the value changes.

disabled marks the setting unavailable and keeps the label and the track in the layout and in the reading order. isLoading marks it busy, the value is being read or written elsewhere, and also stops interaction, because pressing a switch whose value is still in flight is the mistake the state exists to prevent. Neither state rewrites the label.

Props

The cascade is the field family's. radius is registered as full and size as md, so the track is a pill and the density is the one a form uses by default; color is not registered, so it follows the application's defaultColor, and labelAlign follows the field's left.

Switch takes no message and no status: a boolean is either stored or not, so there is no invalid value for a message to explain. What the reader needs before flipping it belongs in description, and what happened afterwards is the page's to show.

Accessibility

  • The control is a real <input type="checkbox"> with role="switch", so Space toggles it, it sits in the tab order without a tabindex, and its state is announced from aria-checked as on or off rather than as checked or unchecked.
  • The label element points at the input with htmlFor, so the visible label is the accessible name, and description is referenced with aria-describedby. The track and the knob are decoration drawn from the input's state, never a second control.
  • isLoading sets aria-busy and disables the input, so a busy switch announces that it is working and refuses a second press while its label stays put. disabled is the native attribute, so the switch leaves the tab order and is announced as unavailable.
  • required is set on the input as well as marked on the label, so the requirement travels with the control instead of living only in the asterisk.

The label and description behave as the field anatomy describes.