Switch

mandatory

ON/OFF toggle with immediate effect. Material parity (`/components/switch`). Distinct from Checkbox — switch implies "this changes state right now"; checkbox implies "I'm submitting this value with the form."

Spec — Switch

Facet *isual*do Koder Design. Material parity: https://m3.material.io/components/switch.

Anatomy

OFF:  ●────         (handle left, track muted)
ON:   ────●         (handle right, track accent)
  • *rack* 52×32 px (default), radius-full pill
  • *andle (thumb)* 24 px circle, shifts left↔right
  • *it zone* 48×48 px

R1 — Switch vs Checkbox

Critical distinction:

Use Switch when… Use Checkbox when…
Action takes effect IMMEDIATELY Action is part of a FORM submit
Single setting, no form context Multiple options or terms acceptance
User can see the system change (WiFi, mute) The change applies on Save
Quick toggle in toolbar Per-row selection in a list

Rule of thumb: if user must click a "Save" button after, use checkbox. If the change persists the moment they toggle, use switch.

R2 — States

State Track Handle
OFF + enabled surface-variant bg surface circle
OFF + hover text-muted 8% bg + ring outline
OFF + focused + focus ring + focus ring
ON + enabled accent bg accent-on circle
ON + hover accent-strong bg + slight scale
ON + focused + focus ring + focus ring
Disabled 38% opacity 38% opacity

R3 — Optional icons

Switch can show icons inside handle/track:

Style Visual
*o icons*(default) Plain pill
*andle icon* Small icon inside handle (24 px) — check/x or feature glyph
*rack icons* Icons at both ends of track (smaller, indicating state semantics)

Optional; doesn't change behavior. Material 3 default includes check/x in handle for accessibility (visual state cue beyond color).

R4 — Animation

  • Handle slides smoothly left↔right on toggle (motion-fast, ~150ms)
  • Track color animates simultaneously
  • Reduced-motion: instant (no slide)
  • Sound (optional, app-specific): subtle click on toggle

R5 — Optimistic state

When toggling has async effect (server save), follow optimistic pattern:

  1. User toggles → switch UI immediately shifts to new state
  2. Async call kicks off in background
  3. If success: stay
  4. If failure: snap back to previous state + show error snackbar

    ("Couldn't enable notifications. Try again.")

NEVER show a spinner WITHIN the switch on async — it freezes the visual feedback.

R6 — Settings convention

In Settings pages, switch rows have this canonical layout:

┌────────────────────────────────────────────────────┐
│ [icon?]  Title                              [●──]  │
│          Optional description text                 │
└────────────────────────────────────────────────────┘
  • Icon (leading, optional)
  • Title (title-medium)
  • Description (body-small muted) below title
  • Switch right-aligned (or left in RTL)
  • Whole row clickable

KoderSettingsTile.toggle() widget (per future settings/patterns.kmd) — exposed by koder_kit.

R7 — Accessibility

  • <input type="checkbox" role="switch"> (HTML standard, both

    attributes)

  • OR native Flutter Switch widget
  • aria-checked="true" / "false" (set automatically with role=switch)
  • Visible focus ring
  • Keyboard: Space toggles
  • Screen reader announces: "Switch, Notifications, on" (or off)
  • High-contrast: not just color — handle position is the primary cue

R8 — Forbidden patterns

  • ❌ Switch for form submission semantics (use checkbox)
  • ❌ Switch without label (always provide accessible name)
  • ❌ Switch that requires confirm dialog after toggle (defeats the

    "immediate" semantic — use checkbox + button instead)

  • ❌ More than ~10 switches in one page (becomes overwhelming;

    group into sub-sections)

  • ❌ Tri-state switch (use radio group for >2 options)

R9 — Per-preset variation

Preset Visual
material3 Pill track + circular handle
ios_cupertino Same shape, slightly larger; uses iOS green for ON
gnome Less rounded pill (radiusmd instead of radiusfull)
windows_11 Mica backdrop track + handle
brutalist Sharp rectangle track + sharp square handle
terminal_classic ASCII [off] / [ON ] text
  • components/checkbox.kmd — vs switch decision
  • interaction/states.kmd — state visuals
  • themes/color-roles.kmd — accent track ON
  • themes/motion.kmd — slide animation

Source: ../home/koder/dev/koder/meta/docs/stack/specs/components/switch.kmd