ui.css · Cross-system: Cross-system reference § Forms
A toggle for a single on/off setting that takes effect immediately
(e.g. enabling a processing step). It is a plain
<input type="checkbox" role="switch">: the native checkbox already provides
keyboard toggling (Space), focus, the change event,
<label> association, and the checked → on/off mapping for
assistive tech. CSS hides the default checkbox and draws a track with a sliding thumb —
no JavaScript and no custom element.
A switch controls one on/off value. For a one-of-many choice use radio buttons; for a value you submit with a form (rather than apply instantly), a plain checkbox is usually clearer.
An <input type="checkbox"> with role="switch", paired with a
<label>. role="switch" both selects the styles and
makes screen readers announce it as a switch — there is no separate class, so the visual and announced control types stay consistent. Wrapping the input in the label (below) makes the label text toggle
the switch with no for/id wiring.
checked.disabled (dimmed, non-interactive).
The common layout is a settings row: a <label> on the left and the switch on
the right, separated with justify-content: space-between. Put the label text in its
own element so the whole row reads as one labelled control.
The switch is driven entirely by the app's design tokens, so its theme updates automatically —
including dark mode, which is handled centrally in index.css
by re-defining the semantic tokens. There is no switch-specific dark-mode CSS.
To restyle only the switch in a given scope — without side effects — override these custom properties:
--switch-size — track height in em (track width is 2×); scales with font-size. Default 1.25em.--switch-track — off-state track. Default var(--surface-2).--switch-track-on — on-state track. Default var(--brand).--switch-thumb — the sliding knob. Default var(--surface-1).--switch-border — knob + track outline (keeps the off thumb ≥ 3:1 against the track). Default: a step stronger than var(--text-2), mixed toward var(--text-1), to meet the contrast requirement in light mode. The outline makes the knob distinguishable: the default thumb (var(--surface-1)) can be almost the same color as the default off track (var(--surface-2)), so the edge provides the necessary contrast. Restyle the thumb and track together, or keep the default outline.
Set them on the switch or on any ancestor scope — an inline style on the wrapping
<label> (as the demo below does), a section, :root — and the value
inherits down. That works because the rule resolves each hook through a var() fallback
(--_track-on: var(--switch-track-on, var(--brand))) instead of declaring
--switch-* on the element itself; declaring them on the element would shadow an
inherited value and prevent the override from taking effect.
role="switch" — screen readers then announce "switch, on/off" instead of "checkbox, checked"; the browser maps the checkbox's checked state to the switch automatically (no manual aria-checked).<label> (wrap the input, or use for/id). The visible text is the accessible name.ui.css control.prefers-reduced-motion: reduce (the states still differ, they just change instantly), and on/off stays distinguishable under Windows High Contrast (forced-colors: active): the custom track and thumb colors are discarded there, so the on state is painted with Highlight/HighlightText and the off state with CanvasText.disabled attribute (used above) is the conventional choice: it dims the switch and removes it from the tab order, and screen readers still announce it as unavailable. If a disabled switch must stay focusable/discoverable (e.g. a toolbar toggle users need to focus to learn why it is unavailable), use aria-disabled="true" instead and block the toggle in script — the component dims both. Disabled controls are exempt from WCAG contrast, so the reduced opacity is fine.See Cross-system reference § Forms for mappings to the Open UI "Active" explainer, Material md-switch, Radix Switch, Bootstrap "Switches", and the WAI-ARIA APG Switch pattern.
.form-fields — input / textarea / select with .form-group layout.disabled / readonly / validation vocabulary.<x-select> — for a one-of-many choice instead of an on/off toggle.