Skip to content

Switch ​

A switch button with role="switch".

Basic Usage ​

Basic usage

Disabled & Loading ​

disabled / loading

loading shows a loading animation and prevents toggling, for async submit scenarios.

Label ​

The label attribute renders a text label next to the switch; clicking the label toggles it (native label association) and provides the accessible name for role="switch". label-position="start" moves the label to the left (default end). Custom content can be placed in the default slot (takes precedence over the label attribute text).

Label

Custom content

Hit-area note: the host shrinks to the actual control width (width: fit-content), so by default the visual width always matches the clickable area. When the host is explicitly stretched (e.g. align-stretch in a vertical oas-space, or width: 100%), clicking anywhere on the row toggles it — the iOS settings row semantics (the inner button and label areas still use their own channels, so no double toggling). Use label for a text hit target beside the switch. Without label, the host can set aria-label (mirrored onto the inner button as the accessible name).

Full-row click when stretched

disabled / loading states block the whole row just like the thumb.

Switch Labels ​

checked-text / unchecked-text render labels on the switch: at medium/large/xl sizes they appear inside the track on the side opposite the thumb; at size="xs" / size="small" the labels move outside the switch.

Switch labels

Sizes ​

size supports five tiers: xs / small / medium (default) / large / xl; invalid values fall back to medium with a warning.

Five sizes

Custom Color ​

color overrides the primary color of the checked state (defaults to --oas-color-primary).

Custom color

Thumb Icons ​

checked-icon / unchecked-icon render icons on the thumb (oas-icons names); the icon follows the on/off state — favorites, day/night mode and similar scenarios:

Thumb icons

Value Mapping ​

true-value / false-value customize the switch value (strings); detail.value of oas-change returns the mapped value (true / false booleans when unset). Reading el.value also returns the current mapped value — useful for form submissions like 'YES' / 'NO'.

true-value / false-value

value: "NO"

Before Change ​

el.beforeChange = (next) => boolean | Promise<boolean> (JS property channel; attributes cannot carry functions): returning false or a rejected Promise cancels the toggle; while an async confirmation is in flight the component enters loading state (spinner + click blocked) to prevent duplicate triggers.

before-change async confirm

Turning off goes through an async confirm (~800ms)

Validation Status ​

status="success" | "warning" | "error" tints the control (error also sets aria-invalid; a host-set aria-invalid gets the same error visuals):

status

Description ​

description renders a muted secondary line under the label explaining what the switch controls (same contract as the oas-checkbox / oas-radio description); rich content in slot[name="description"] wins over the attribute text:

Description

Custom label Rich HTML descriptions supported

Card Variant (variant="card") ​

variant="card" upgrades the switch into a choice card: a bordered card wraps the thumb + label + description, the whole card is clickable (click anywhere on the card to toggle), and the selected state tints the border with the primary color over a faint background (same visual language as the oas-checkbox / oas-radio choice cards); disabled / status also apply to the card border. Ideal for settings-style per-item switch lists:

Card variant

Custom Width ​

--oas-switch-width / --oas-switch-height / --oas-switch-thumb-size CSS variables override the track width / height / thumb size across size tiers:

CSS variable sizing

Events ​

oas-change (detail: { checked, value }), oas-focus / oas-blur (focus enters / leaves the component).

Toggle events

Controlled usage: when the host owns the state, bind the checked attribute and write it back on oas-change (in Vue: :checked="x" + @oas-change="x = $event.detail.checked").

required ​

required (native validation chain)

required drives the native validation chain (form-associated): when unfilled, checkValidity() returns false (valueMissing) and native form submission is blocked; it recovers to :valid once filled.

API ​

oas-switch ​

Attributes ​

AttributeDescriptionTypeDefault
aria-labelAccessible name (host override channel; explicit value wins over label derivation)——
checkedWhether onboolean—
checked-iconChecked-state thumb icon (oas-icon name)string—
checked-textLabel shown when on; inside the track at medium/large/xl, outside at xs/small——
colorCustom primary color for the on state, overrides --oas-color-primary (CSS color value)——
descriptionSecondary description text (muted line under the label; slot[name=description] rich content wins over the attribute text), same contract as checkbox/radio descriptionstring—
disabledDisabledboolean—
false-valueMapped value when uncheckedstring—
labelLabel text (label channel; clicking the label toggles; same-named slot for rich content)string—
label-positionLabel position: end (default, right) / start (left)string—
loadingLoading state, prevents togglingboolean—
requiredRequired marker (drives the native valueMissing validation chain: off counts as unfilled)boolean—
sizeSize: xs / small / medium (default) / large / xl; invalid values fall back to medium with a warningstringmedium
statusValidation status: error / warning / success; error mirrors aria-invalidstring—
true-valueMapped value when checked (read via the value getter)string—
unchecked-iconUnchecked-state thumb iconstring—
unchecked-textLabel shown when off; inside the track at medium/large/xl, outside at xs/small——
variantVariant: default (plain thumb) / card (a bordered card wrapping the thumb + label + description; whole card clickable, selected state tints the border, aligned with the checkbox/radio choice card); invalid values silently fall back to defaultstring—

Events ​

EventDescription
oas-blurFires on blur
oas-changeToggle, detail: { checked, value } (value is the mapped value)
oas-focusFires on focus

Slots ​

NameDescription
defaultSwitch content (label / rich content)
descriptionRich description content (takes precedence over the description attribute text)

CSS Variables ​

CSS VariableDescriptionDefault
--oas-glass-refractionLiquid-glass edge refraction filter (active under data-glass, default none); for local opt-out override with an empty value (--oas-glass-refraction: ;)—not none (mixing none with button-state brightness() invalidates the whole filter declaration)none
--oas-switch-height—22px
--oas-switch-on-colorLabel text color inside the on-track (when color overrides the track background, the component injects a dark/light text color by luminance; falls back to var(--oas-color-bg))var(--oas-color-bg)
--oas-switch-thumb-size—18px
--oas-switch-width—40px

Released under the MIT OR Apache-2.0 License.