Switch
import { Switch } from '@absoluteui/components/switch';import '@absoluteui/components/switch/style.css';Using Angular? See Switch for Angular.
What it does
Section titled “What it does”An on/off setting that takes effect immediately. Switch renders a native <input type="checkbox" role="switch"> restyled as a track, with a decorative thumb whose position shows the state. Switches have no required state: a switch is a setting, not a question. Validity is always valid unless a custom error is set, for example when saving the setting failed.
When to use
Section titled “When to use”- A binary setting that applies immediately, such as enabling notifications or dark mode.
- Settings pages where each row toggles one feature.
When not to use
Section titled “When not to use”- A choice that is only applied when a form is submitted: use Checkbox.
- A choice the user must confirm (“I agree”): use a required Checkbox.
- More than two states: use Radio Group or Select.
Examples
Section titled “Examples”Setting that applies immediately
Section titled “Setting that applies immediately”import { Switch } from '@absoluteui/components/switch';
const host = document.createElement('div');document.body.append(host);const notifications = Switch.create(host, { label: 'Email notifications', description: 'Weekly summary of activity' });host.addEventListener('aui-change', () => { document.documentElement.dataset.notifications = String(notifications.checked);});Reporting a failed save
Section titled “Reporting a failed save”import { Switch } from '@absoluteui/components/switch';
const host = document.createElement('div');document.body.append(host);const sync = Switch.create(host, { label: 'Sync across devices', checked: true });
async function save(on: boolean): Promise<void> { const response = await fetch('/api/settings/sync', { method: 'PUT', body: JSON.stringify({ on }) }); if (!response.ok) { sync.setChecked(!on); sync.setCustomError('Could not save. Try again.'); sync.reportValidity(); }}
host.addEventListener('aui-change', () => { void save(sync.checked);});import { Switch } from '@absoluteui/components/switch';import '@absoluteui/components/switch/style.css';
const host = document.querySelector<HTMLElement>('#dark-mode');if (host) { const dark = Switch.create(host, { label: 'Dark mode' }); host.addEventListener('aui-change', () => { document.documentElement.dataset.auiTheme = dark.checked ? 'absolute-dark' : 'absolute-default'; });}More usage
Section titled “More usage”import { Switch } from '@absoluteui/components/switch';
const host = document.createElement('div');document.body.append(host);Switch.create(host, { label: 'Email notifications', description: 'Weekly summary of activity' });Anatomy
Section titled “Anatomy”<div class="aui-field aui-switch" data-aui-control> (consumer host) <div class="aui-switch__row"> <span class="aui-switch__control"> <input type="checkbox" role="switch" class="aui-switch__input"> <span class="aui-switch__thumb" aria-hidden="true"> </span> <label class="aui-field__label aui-switch__label" for=input>Label</label> </div> <div class="aui-field__description"> (optional) <div class="aui-field__error aui-validation-message"> (custom error, when shown)</div>API reference
Section titled “API reference”Factory
Section titled “Factory”Switch.create(host: HTMLElement, options: SwitchOptions): SwitchGlobal configuration key: switch (see Configuration).
Options
Section titled “Options”| Option | Type | Default | Description |
|---|---|---|---|
label |
string |
Visible label and accessible name; clicking it toggles the switch. Required. | |
hideLabel |
boolean |
false |
Visually hide the label; it remains the accessible name. |
checked |
boolean |
false |
Initial on/off state; also restored by reset(). |
value |
string |
"on" |
Submitted value when on. |
name |
string |
Form field name. | |
description |
string |
Help text referenced by aria-describedby. | |
disabled |
boolean |
false |
Disables the switch. |
icons |
Partial<{ error: IconRef }> |
Icon slot overrides. | |
validationTiming |
'blur' | 'input' | 'submit' |
"blur" |
When a custom error message first appears; afterwards it updates live. Globally configurable. |
locale |
string |
"en-US" |
Message locale. Globally configurable. Inherited from common configuration. |
Properties
Section titled “Properties”| Property | Type | Description |
|---|---|---|
host |
HTMLElement |
Consumer host; its children are owned by the component. |
input |
HTMLInputElement |
The native checkbox with role=switch. |
checked |
boolean |
Current on/off state. |
value |
string |
Submitted value when on. |
name |
string | null |
Form field name. |
label |
string |
Label text. |
disabled |
boolean |
Disabled state. |
validity |
FieldValidity |
Always valid unless a custom error is set. |
dirty |
boolean |
State differs from the initial state. |
touched |
boolean |
Focus has left the control at least once. |
options |
Readonly<SwitchOptions> |
Current instance options. |
Methods
Section titled “Methods”| Method | Description |
|---|---|
setChecked(checked: boolean): void |
Programmatic state (no events); clears an external custom error. |
update(options: Partial<SwitchOptions>): void |
Merge and apply options. |
reportValidity(): boolean |
Show a custom error now and return validity. |
setCustomError(message: string | null): void |
External error, for example a failed save; cleared when the user toggles. |
getFormValue(): string | null |
value when on, otherwise null. |
focus(): void |
Focus the switch. |
reset(): void |
Restore the initial state and clear dirty/touched/submitted state. |
destroy(): void |
Remove rendering, listeners, registration, and subscriptions. |
Events
Section titled “Events”| Event | Detail | Bubbles | Cancelable | Description |
|---|---|---|---|---|
aui-change |
{ checked: boolean; value: string } |
Yes | No | The user toggled the switch. |
CSS classes
Section titled “CSS classes”All rules live in the aui.components cascade layer, so application styles override them without specificity battles.
| Class | Purpose |
|---|---|
aui-field aui-switch |
Host. |
aui-switch--invalid | --disabled |
State modifiers on the host. |
aui-field__label | __description | __error |
Shared field chrome. |
aui-switch__row |
Track and label row. |
aui-switch__control |
Positioning wrapper for the track and thumb. |
aui-switch__input |
Native input, restyled as the track. |
aui-switch__thumb |
Decorative thumb; its position shows the state. |
aui-switch__label |
The label (also aui-field__label). |
Icon slots
Section titled “Icon slots”| Slot | Default icon |
|---|---|
error |
alert-circle |
Design tokens
Section titled “Design tokens”Tokens this stylesheet reads (verified in CI). Override them in a theme or with the Theme Designer.
--aui-border-width | --aui-color-border | --aui-color-border-strong | --aui-color-disabled-bg | --aui-color-error-fg | --aui-color-focus-ring | --aui-color-on-primary | --aui-color-primary | --aui-color-surface | --aui-color-surface-sunken | --aui-color-text | --aui-color-text-disabled | --aui-color-text-muted | --aui-duration-fast | --aui-easing-standard | --aui-focus-ring-offset | --aui-focus-ring-width | --aui-font-family-sans | --aui-font-size-md | --aui-font-size-sm | --aui-font-weight-medium | --aui-font-weight-regular | --aui-icon-size-sm | --aui-line-height-normal | --aui-line-height-tight | --aui-radius-pill | --aui-space-1 | --aui-space-2 | --aui-switch-height | --aui-switch-width | --aui-touch-target-min
TypeScript definitions
Section titled “TypeScript definitions”type ValidationTiming = 'blur' | 'input' | 'submit';interface SwitchIcons { error: IconRef }interface SwitchChangeDetail { checked: boolean; value: string }Accessibility
Section titled “Accessibility”Pattern: Native <input type=“checkbox” role=“switch”> with a <label for> association (WAI-ARIA APG Switch).
Keyboard
Section titled “Keyboard”| Key | Context | Action |
|---|---|---|
| Tab / Shift+Tab | Any | Moves focus to and from the switch. |
| Space | Switch focused | Toggles on/off (native). |
| Element | Role |
|---|---|
| input | switch (explicit on a native checkbox; checked state maps to on/off) |
| thumb and icons | none (aria-hidden=true) |
ARIA attributes
Section titled “ARIA attributes”| Attribute | Element | Value |
|---|---|---|
role |
input | “switch” |
aria-describedby |
input | Help text and visible error message ids |
aria-invalid |
input | “true” only while a custom error message is shown |
The native input (the track) is the focus target and shows a color-focus-ring outline on :focus-visible.
WCAG 2.2 success criteria addressed
Section titled “WCAG 2.2 success criteria addressed”Automated test results: Accessibility and compliance.
Notes and known caveats
Section titled “Notes and known caveats”- The state is shown by the thumb position as well as by color.
- Clicking the label toggles the switch, extending the hit target.
- Enter does not toggle (native checkbox behavior); Space does.
- Switches have no required state; a failed save can be reported with setCustomError.
- Screen-reader announcement of role=switch on/off has not yet been manually verified with NVDA, JAWS, and VoiceOver.
Behavior
Section titled “Behavior”States
Section titled “States”off, on, hover, focus-visible, disabled, disabled on, invalid (custom error shown).
State transitions
Section titled “State transitions”| From | Trigger | To |
|---|---|---|
| off | click, label click, or Space | on; aui-change |
| on | click, label click, or Space | off; aui-change |
| any | focus leaves the host | touched; a custom error is shown (blur timing) |
| invalid (custom error) | user toggles | custom error cleared |
| any | reset() |
initial state; pristine, untouched |
Accessibility notes
Section titled “Accessibility notes”- The state is shown by thumb position as well as color (WCAG 1.4.1).
- The label is clickable, so the target is the whole row (WCAG 2.5.8).
- The label should describe the setting and stay constant; do not change it to “On”/“Off”.
- Reduced motion removes the thumb transition.
- Manual screen-reader verification is pending (see Known limitations).
Responsive behavior
Section titled “Responsive behavior”The track is fixed-size (switch-width by switch-height); the label wraps beside it. Help text and messages align with the label.
Right-to-left
Section titled “Right-to-left”The thumb uses inset-inline-start, so “on” moves it to the inline end in both directions (right in LTR, left in RTL) without direction-specific rules.
Theming
Section titled “Theming”Off: color-surface-sunken track with a color-border-strong boundary and thumb. On: color-primary track with a color-on-primary thumb. High-contrast themes widen border-width. In forced-colors mode the track uses Canvas/CanvasText when off and Highlight/HighlightText when on, and disabled uses GrayText, with forced-color-adjust: none.
Global configuration
Section titled “Global configuration”configureAbsoluteUI({ components: { switch: { validationTiming: 'submit' } } });Changes apply to existing instances immediately. validationTiming only affects when a custom error first appears.
Component configuration
Section titled “Component configuration”Instance options override global and theme defaults. All options are dynamic.
icons.error (default alert-circle). The thumb is a CSS shape, not an icon.
Security
Section titled “Security”All text uses textContent. CSP-safe: no inline styles or HTML strings.
Data handling
Section titled “Data handling”No persistence, network access, or telemetry. With name, the native input submits name=value when on.
Performance
Section titled “Performance”Two listeners per instance (change, focusout), a shared document-level pointer tracker, and one configuration subscription. Target: under 1 ms per Switch.create; not yet covered by the performance test.
Supported data scale
Section titled “Supported data scale”One value per instance. Not yet included in the 1,000-instance performance test.
Edge cases
Section titled “Edge cases”reportValidity()returnstrueunless a custom error is set.setChecked()clears a custom error, so revert the state first and then set the error when a save fails.- A disabled switch is not submitted natively, but
getFormValue()still reports its value.
Errors
Section titled “Errors”| Code | Category | Cause |
|---|---|---|
SWITCH_OPTIONS |
configuration | Missing label or non-string value. |
Validation (validity.error) |
validation | custom only (set through setCustomError). |
A failed construction leaves no rendering, listeners, or subscriptions behind.
Known limitations
Section titled “Known limitations”- No
requiredorvalidateoption by design; use a Checkbox for choices that must be confirmed. - No on/off text inside the track.
- The track alone is 2.25rem by 1.25rem; the 24px target is met by the row and label.
- Screen-reader behavior of
role="switch"has not yet been manually verified with NVDA, JAWS, and VoiceOver.
Unsupported scenarios
Section titled “Unsupported scenarios”- A mixed/indeterminate state.
- HTML inside the label.