Toggle

Instant on-or-off with optimistic feedback.

v1.0.0·Updated Jul 8, 2026 · 10:45
Live Demo — Fully Interactive
Sizes — click to flip
L · 28px
M · 24px
S · 19px
States
Off
Onwarm #FF7A00 when on
Disabled
Configuration
Size
State
Label
Text
Email notifications
<Toggle checked={on} onChange={setOn} size="m" label="Email notifications" />
Behavior — The Engineering Contract
Prop / eventTypeNotes
checkedbooleanControlled on/off state
onChange(next) => voidFires on click, Enter and Space
sizel · m · sTrack 48 / 40 / 32px wide
label / descriptionstringRow is clickable; description is optional
disabledbooleanBlocks interaction, opacity 0.42
role="switch"a11yaria-checked reflects state; Tab-focusable

A toggle changes state immediately and never shows a spinner on itself. If the change needs the network, apply it optimistically and reconcile in the background — the Optimistic tab in the demo above does exactly that.

Anatomy
Email notifications
1TrackThe pill. Grey when off, warm #FF7A00 when on — the state is the colour.
2KnobSlides across with a spring on change. Its position is the second cue.
3LabelNames the state, not the action. The whole row is one click target.
Do's and Don'ts
✓ Do
Dark mode

Use a toggle for an instant, standalone on/off with no confirmation needed.

✕ Don't
Delete account

Never toggle a destructive or irreversible action. That belongs to a button and a confirm.

✓ Do
Auto-save

Label the state, not the verb. "Auto-save" reads clearly whether it is on or off.

✕ Don't
Turn off auto-save?

Don't phrase the label as a question or an action. A toggle is a state, not a prompt.

In context: Examples
A · Settings list
Email notificationsDesktop alertsWeekly digest

Controls align to the right edge, labels to the left. One row per setting.

B · Inline in a toolbar
LIVE

Small size pairs with a short mono label for compact, dense surfaces.

C · With a description
Two-factor authAsk for a code at every new sign-in.

A description sits under the label when the choice needs explaining.

Measurements & Tokens
TokenValueRole
--tg-track-l/m/s48×28 / 40×24 / 32×19Track size per scale
--tg-knob-l/m/s22 / 18 / 14pxSliding knob diameter
--tg-off-track#26262BOff track fill
--tg-off-knob#9AA0A8Off knob
--tg-on#FF7A00On track & border (the one light)
--tg-on-knob#FFFFFFOn knob
--tg-easecubic-bezier(.34,1.56,.64,1)Knob spring, 0.22s
--tg-focusrgba(255,122,0,.35)3px focus-visible ring
Code
<button class="o-toggle o-toggle--m" role="switch" aria-checked="true"></button>

<label class="o-toggle-row">
  <button class="o-toggle o-toggle--m is-on" role="switch" aria-checked="true"></button>
  <span>Email notifications</span>
</label>