Skip to main content
xriptxr

Switch

Info:Controls
71

An on/off toggle that applies immediately, with an accessible name and optional state labels.

toggle on off boolean flip

Live demo

live · @xtyle/astro

Switch

A settings panel

Email notifications

Get a digest when something changes.

Email notifications

Reduced motion

Honor system animation preferences.

Reduced motionOff

Beta channel

Locked while a build is in flight.

Beta channel

States & sizes

Off

off

On

on

With labelsYes

labelled

Small

sm

Disabled

disabled

Shape, orientation, direction & label

Vertical follows a wall switch (down off, up on); reverse flips the on/off direction; labelSide moves the label without touching behavior.

Square

square

Vertical

vertical (up = on)

Reversed

reverse (on at left)

Vertical reversed

vertical + reverse

Label after

labelSide=end

Every tone

Toggle all

Toggle any switch: the track lights up while the knob stays a darkened cast of the tone, so it reads in both states. “Toggle all” flips the lot.

Accents

accent accent-2 accent-3 accent-4 neutral

Statuses

success info warn danger

Named hues

red orange yellow green blue purple brown pink cyan gray white black

Switch is a role="switch" toggle for a setting that takes effect immediately, distinct from a checkbox that stages a value until a form submit. It renders a native <button> track with a sliding thumb, so pointer, Space, and Enter all flip it and the state lives in aria-checked.

An optional leading label and optional on-label/off-label state text make the toggle self-describing, and it is form-associated: give it a name (and optional value) and it contributes to form data only while on. Two sizes: the default md and a compact sm.

When to use

How this component composes with the rest of the set.

Pair with Field or a form to capture the toggle; give it a name so it contributes to submitted data.
Use label for a persistent name, or on-label/off-label for a control whose name is its current state.
For a staged value that only applies on submit, reach for a checkbox instead. A switch applies immediately.

Props

15 props, straight from the manifest.

PropTypeDefaultBindingsDescription
checked boolean false
html svelte astro
The on/off state. Two-way bindable in Svelte; reflected to aria-checked and the element's .checked.
focusable boolean true
html svelte astro
Set false to keep the control out of sequential focus navigation, for an app driving selection from its own keyboard cursor. The host's own tabindex cannot express this, because focus lands on the inner control rather than the host, and setting it there from outside does not survive the next render.
disabled boolean false
html svelte astro
Disables interaction; mutes the track, suppresses the overlay, and sets aria-disabled.
size Size
sm md
md
html svelte astro
Control size. Only sm differs from the default.
tone FullTone
accent neutral danger success warn info accent-2 accent-3 accent-4 red orange yellow green blue purple brown pink cyan gray white black
accent
html svelte astro
Color of the on-state track and thumb ink. Any of the semantic roles, accent variants, or named hues.
shape "pill" | "square"
pill square
pill
html svelte astro
Track and thumb corner shape: the default rounded pill, or a squared track for a chunkier control.
orientation "horizontal" | "vertical"
horizontal vertical
horizontal
html svelte astro
Track axis. Horizontal slides the thumb left-to-right (on at the right); vertical stands the track up and follows a wall switch: down is off, up is on.
reverse boolean false
html svelte astro
Flip the on/off direction: horizontal puts on at the left, vertical puts on at the bottom. The label is unaffected.
labelSide html: label-side "start" | "end"
start end
start
html svelte astro
Which side the label sits on relative to the track. end puts the control first and the label after it.
label string
html svelte astro
Visible leading label, also wired as the accessible name via aria-labelledby.
labelledby string
html svelte astro
ID of an external element that names the toggle. Takes precedence over label.
onLabel html: on-label string
html svelte astro
State text shown (and announced as the name, absent label) when on.
offLabel html: off-label string
html svelte astro
State text shown (and announced as the name, absent label) when off.
name string
html svelte astro
Form field name; the toggle contributes value to form data only while on.
value string on
html svelte astro
The value submitted with the form when the toggle is on.

Events

What the component emits, and what rides along on event.detail. The name in the first column is the one addEventListener takes.

EventDetailBindingsDescription
change { checked, value }
html svelte astro
The switch was toggled.

Appearance

Variants

square

.xtyle-switch--square

Squared track and thumb corners.

vertical

.xtyle-switch--vertical

Track stood on its end; down is off, up is on.

reverse

.xtyle-switch--reverse

On/off direction flipped (on at the left, or the bottom when vertical).

label-end

.xtyle-switch--label-end

Label after the control instead of before it.

Sizes

sm

.xtyle-switch--sm

Compact.

md

default
.xtyle-switch

Default.

States

on

.xtyle-switch__track[aria-checked="true"]

Toggle is on: the track fills with the chosen tone (accent by default) and the thumb slides to the end.

hover

.xtyle-switch__track:hover::after

Pointer over the track: overlay paints the hover tint.

active

.xtyle-switch__track:active::after

Track pressed: overlay paints the press tint.

focus-visible

.xtyle-switch__track:focus-visible

Keyboard focus: a token-colored ring, plus a transparent outline that becomes real in forced-colors mode.

disabled

.xtyle-switch__track:disabled, .xtyle-switch__track[aria-disabled="true"]

Non-interactive: muted track and thumb, overlay suppressed.

Anatomy

The named parts that make up the component. A ::part() handle is reachable from your own stylesheet; the class beside it is the component's internal selector, which a shadow boundary keeps to itself.

switch

Success:::part(switch) .xtyle-switch

The row wrapper carrying the size and disabled classes and laying out label, track, and state text.

--font-sans --text-body --leading-tight --fg-0 --space-2

track

Success:::part(track) .xtyle-switch__track

The interactive role="switch" button: the pill the thumb slides within.

--space-7 --space-5 --space-2 --border-thin --line-2 --radius-full --neutral-bg --duration-base --ease-emphasized --duration-fast --ease-standard

thumb

Success:::part(thumb) .xtyle-switch__thumb

The circular knob: a darkened cast of the track's tone, kept visible on and off.

--space-1 --radius-full --elevation-1

label

Success:::part(label) .xtyle-switch__label

The visible leading label that names the toggle and is referenced as its accessible name.

state

Success:::part(state) .xtyle-switch__state

Optional trailing on/off state text; becomes the accessible name when no other label is given.

--fg-2 --text-sm

overlay

internal .xtyle-switch__track::after

The pseudo-element behind the track that paints hover and active state tints.

--state-hover --state-press

Tokens & coverage

What the component consumes, checked live against what the algorithm produces.

Success:fully covered 71/71 consumed tokens produced default register: 310 tokens

Live coverage check against the xtyle-default register (derive(xtyleDefault, { anchors })coverComponent(manifest, register)). Every token this component consumes must be a key the algorithm produces.

--accent --accent-2 --accent-2-fg --accent-3 --accent-3-fg --accent-4 --accent-4-fg --accent-fg --black --black-fg --blue --blue-fg --border-normal --border-thick --border-thin --brown --brown-fg --cyan --cyan-fg --danger --danger-fg --duration-base --duration-fast --ease-emphasized --ease-standard --elevation-1 --fg-0 --fg-2 --fg-disabled --font-sans --gray --gray-fg --green --green-fg --info --info-fg --leading-tight --line-2 --neutral --neutral-bg --neutral-fg --orange --orange-fg --pink --pink-fg --purple --purple-fg --radius-full --radius-sm --red --red-fg --ring --space-1 --space-2 --space-4 --space-5 --space-6 --space-7 --state-disabled --state-hover --state-press --success --success-fg --text-body --text-sm --warn --warn-fg --white --white-fg --yellow --yellow-fg

Accessibility

Renders a native <button> with role="switch", so click, Space, and Enter all toggle it; Space's default scroll is prevented.
State is carried in aria-checked and mirrored on the element's reflected .checked, never by color alone.
Requires an accessible name: labelledby wins, then label, then the on/off state text; the binding warns at runtime when none is present.
The thumb and state-only labels are wired so the toggle is always announced with a name, even when only on-label/off-label are given.
Focus is shown with a token ring and a transparent outline that the forced-colors base rule promotes to a real system outline.
disabled blocks interaction and sets aria-disabled; the track is muted and the overlay suppressed.

Code

Labels, tones, shapes, and form association

A named toggle, on/off state text, the compact size, a toned switch, the square / vertical / reversed variants, a form-bound switch, and a disabled one.

<xtyle-switch label="Wi-Fi" checked></xtyle-switch>

<xtyle-switch label="Notifications" on-label="On" off-label="Off"></xtyle-switch>

<xtyle-switch size="sm" label="Compact mode"></xtyle-switch>

<xtyle-switch label="Alerts" tone="danger" checked></xtyle-switch>

<xtyle-switch label="Square" shape="square" checked></xtyle-switch>

<xtyle-switch label="Vertical" orientation="vertical" checked></xtyle-switch>

<xtyle-switch label="Reversed" reverse checked></xtyle-switch>

<xtyle-switch label="Label after" label-side="end" checked></xtyle-switch>

<xtyle-switch label="Sync" name="sync" value="enabled" checked></xtyle-switch>

<xtyle-switch label="Locked" disabled checked></xtyle-switch>