Switches

Switches toggle a single option on or off.

Basic Switch

<label class="Switch">
<input type="checkbox">
<span class="Switch-slider"></span>
</label>
<label class="Switch">
    <input type="checkbox">
    <span class="Switch-slider"></span>
</label>

States

<div style="display: flex; gap: var(--space-6); align-items: center;">
<label class="Switch">
<input type="checkbox">
<span class="Switch-slider"></span>
</label>
<label class="Switch">
<input type="checkbox" checked>
<span class="Switch-slider"></span>
</label>
<label class="Switch">
<input type="checkbox" disabled>
<span class="Switch-slider"></span>
</label>
<label class="Switch">
<input type="checkbox" checked disabled>
<span class="Switch-slider"></span>
</label>
</div>
<input type="checkbox">           <!-- Off -->
<input type="checkbox" checked>   <!-- On -->
<input type="checkbox" disabled>  <!-- Disabled off -->
<input type="checkbox" checked disabled>  <!-- Disabled on -->

Sizes

<div style="display: flex; gap: var(--space-6); align-items: center;">
<label class="Switch Switch--small">
<input type="checkbox" checked>
<span class="Switch-slider"></span>
</label>
<label class="Switch">
<input type="checkbox" checked>
<span class="Switch-slider"></span>
</label>
<label class="Switch Switch--large">
<input type="checkbox" checked>
<span class="Switch-slider"></span>
</label>
</div>
<label class="Switch Switch--small">...</label>
<label class="Switch">...</label>
<label class="Switch Switch--large">...</label>

With Label

<div style="display: flex; flex-direction: column; gap: var(--space-4);">
<label class="Switch-label">
<span class="Switch-label-text">
<span>Dark mode</span>
<small style="color: var(--fg-3);">Use dark theme across the app</small>
</span>
<span class="Switch">
<input type="checkbox">
<span class="Switch-slider"></span>
</span>
</label>
<label class="Switch-label">
<span class="Switch-label-text">
<span>Notifications</span>
<small style="color: var(--fg-3);">Receive push notifications</small>
</span>
<span class="Switch">
<input type="checkbox" checked>
<span class="Switch-slider"></span>
</span>
</label>
</div>
<label class="Switch-label">
    <span class="Switch-label-text">
        <span>Dark mode</span>
        <small>Use dark theme across the app</small>
    </span>
    <span class="Switch">
        <input type="checkbox">
        <span class="Switch-slider"></span>
    </span>
</label>

In a Form

<div style="width: 320px; display: flex; flex-direction: column; gap: var(--space-3);">
<label class="Switch-label" style="padding: var(--space-3) 0; border-bottom: 1px solid var(--bd);">
<span>Email notifications</span>
<span class="Switch Switch--small">
<input type="checkbox" checked>
<span class="Switch-slider"></span>
</span>
</label>
<label class="Switch-label" style="padding: var(--space-3) 0; border-bottom: 1px solid var(--bd);">
<span>SMS alerts</span>
<span class="Switch Switch--small">
<input type="checkbox">
<span class="Switch-slider"></span>
</span>
</label>
<label class="Switch-label" style="padding: var(--space-3) 0; border-bottom: 1px solid var(--bd);">
<span>Marketing emails</span>
<span class="Switch Switch--small">
<input type="checkbox">
<span class="Switch-slider"></span>
</span>
</label>
</div>

Common Patterns

Settings Panel

Preferences
<div style="width: 360px; border: 1px solid var(--bd); border-radius: var(--radius-md); overflow: hidden;">
<div style="padding: var(--space-3) var(--space-4); border-bottom: 1px solid var(--bd); font-weight: 600;">Preferences</div>
<div style="display: flex; flex-direction: column;">
<label class="Switch-label" style="padding: var(--space-3) var(--space-4); border-bottom: 1px solid var(--bd);">
<span class="Switch-label-text"><span>Dark mode</span><small style="color: var(--fg-3);">Use dark theme across the app</small></span>
<span class="Switch"><input type="checkbox" checked><span class="Switch-slider"></span></span>
</label>
<label class="Switch-label" style="padding: var(--space-3) var(--space-4); border-bottom: 1px solid var(--bd);">
<span class="Switch-label-text"><span>Compact view</span><small style="color: var(--fg-3);">Reduce spacing in lists</small></span>
<span class="Switch"><input type="checkbox"><span class="Switch-slider"></span></span>
</label>
<label class="Switch-label" style="padding: var(--space-3) var(--space-4);">
<span class="Switch-label-text"><span>Sounds</span><small style="color: var(--fg-3);">Play notification sounds</small></span>
<span class="Switch"><input type="checkbox" checked><span class="Switch-slider"></span></span>
</label>
</div>
</div>

Feature Flags

BETA_EDITOR Beta
AI_ASSIST New
DARK_MODE
<div style="width: 400px; display: flex; flex-direction: column; gap: var(--space-2);">
<div style="display: flex; align-items: center; justify-content: space-between; padding: var(--space-2) var(--space-3); background: var(--bg-s); border-radius: var(--radius-sm);">
<div style="display: flex; align-items: center; gap: var(--space-2);">
<code style="font-size: 0.8rem;">BETA_EDITOR</code>
<span class="Badge Badge--warning" style="font-size: 0.65rem;">Beta</span>
</div>
<label class="Switch Switch--small"><input type="checkbox" checked><span class="Switch-slider"></span></label>
</div>
<div style="display: flex; align-items: center; justify-content: space-between; padding: var(--space-2) var(--space-3); background: var(--bg-s); border-radius: var(--radius-sm);">
<div style="display: flex; align-items: center; gap: var(--space-2);">
<code style="font-size: 0.8rem;">AI_ASSIST</code>
<span class="Badge Badge--info" style="font-size: 0.65rem;">New</span>
</div>
<label class="Switch Switch--small"><input type="checkbox"><span class="Switch-slider"></span></label>
</div>
<div style="display: flex; align-items: center; justify-content: space-between; padding: var(--space-2) var(--space-3); background: var(--bg-s); border-radius: var(--radius-sm);">
<div style="display: flex; align-items: center; gap: var(--space-2);">
<code style="font-size: 0.8rem;">DARK_MODE</code>
</div>
<label class="Switch Switch--small"><input type="checkbox" checked><span class="Switch-slider"></span></label>
</div>
</div>

Notification Preferences

Channel Email Push SMS
Comments
Mentions
Updates
<div style="width: 340px;">
<table style="width: 100%; border-collapse: collapse;">
<thead>
<tr style="border-bottom: 1px solid var(--bd);">
<th style="text-align: left; padding: var(--space-2) 0; font-size: 0.8rem; color: var(--fg-3);">Channel</th>
<th style="text-align: center; padding: var(--space-2); font-size: 0.8rem; color: var(--fg-3);">Email</th>
<th style="text-align: center; padding: var(--space-2); font-size: 0.8rem; color: var(--fg-3);">Push</th>
<th style="text-align: center; padding: var(--space-2); font-size: 0.8rem; color: var(--fg-3);">SMS</th>
</tr>
</thead>
<tbody>
<tr style="border-bottom: 1px solid var(--bd);">
<td style="padding: var(--space-2) 0; font-size: 0.875rem;">Comments</td>
<td style="text-align: center;"><label class="Switch Switch--small"><input type="checkbox" checked><span class="Switch-slider"></span></label></td>
<td style="text-align: center;"><label class="Switch Switch--small"><input type="checkbox" checked><span class="Switch-slider"></span></label></td>
<td style="text-align: center;"><label class="Switch Switch--small"><input type="checkbox"><span class="Switch-slider"></span></label></td>
</tr>
<tr style="border-bottom: 1px solid var(--bd);">
<td style="padding: var(--space-2) 0; font-size: 0.875rem;">Mentions</td>
<td style="text-align: center;"><label class="Switch Switch--small"><input type="checkbox" checked><span class="Switch-slider"></span></label></td>
<td style="text-align: center;"><label class="Switch Switch--small"><input type="checkbox" checked><span class="Switch-slider"></span></label></td>
<td style="text-align: center;"><label class="Switch Switch--small"><input type="checkbox" checked><span class="Switch-slider"></span></label></td>
</tr>
<tr>
<td style="padding: var(--space-2) 0; font-size: 0.875rem;">Updates</td>
<td style="text-align: center;"><label class="Switch Switch--small"><input type="checkbox" checked><span class="Switch-slider"></span></label></td>
<td style="text-align: center;"><label class="Switch Switch--small"><input type="checkbox"><span class="Switch-slider"></span></label></td>
<td style="text-align: center;"><label class="Switch Switch--small"><input type="checkbox"><span class="Switch-slider"></span></label></td>
</tr>
</tbody>
</table>
</div>

Customization

Override switch styles using CSS custom properties:

/* Custom accent color */
.Switch input:checked + .Switch-slider {
  background: oklch(55% 0.2 150);
  border-color: oklch(55% 0.2 150);
}

/* Larger thumb */
.Switch--xl .Switch-slider::before {
  width: 24px;
  height: 24px;
}

/* Square switch (no rounded corners) */
.Switch--square .Switch-slider {
  border-radius: var(--radius-sm);
}
.Switch--square .Switch-slider::before {
  border-radius: var(--radius-xs);
}

/* Custom track colors */
.Switch--danger input:checked + .Switch-slider {
  background: oklch(55% 0.2 25);
  border-color: oklch(55% 0.2 25);
}

API Reference

Base Classes

ClassDescription
.Switch Base switch wrapper (label element, required)
.Switch-slider Visual slider/track element
.Switch-label Container for switch with text label
.Switch-label-text Text wrapper (supports title + description)

Size Classes

ClassDescription
.Switch--small Smaller switch size
.Switch--large Larger switch size

Attributes

AttributeDescription
checked Checked/active state (on)
disabled Non-interactive state

CSS Reference

/* Base switch */
.Switch {
  position: relative;
  display: inline-flex;
  align-items: center;
  cursor: pointer;
}

.Switch input {
  position: absolute;
  opacity: 0;
  width: 0;
  height: 0;
}

/* Track */
.Switch-slider {
  position: relative;
  width: 44px;
  height: 24px;
  background: var(--bg-s);
  border: 1px solid var(--bd-s);
  border-radius: 999px;
  transition: background 0.2s, border-color 0.2s;
}

/* Thumb */
.Switch-slider::before {
  content: "";
  position: absolute;
  top: 2px;
  left: 2px;
  width: 18px;
  height: 18px;
  background: white;
  border-radius: 50%;
  transition: transform 0.2s;
  box-shadow: var(--shadow-sm);
}

/* Checked state */
.Switch input:checked + .Switch-slider {
  background: var(--accent);
  border-color: var(--accent);
}

.Switch input:checked + .Switch-slider::before {
  transform: translateX(20px);
}

/* Focus ring */
.Switch input:focus-visible + .Switch-slider {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* Disabled */
.Switch input:disabled + .Switch-slider {
  opacity: 0.5;
  cursor: not-allowed;
}

/* Small */
.Switch--small .Switch-slider {
  width: 34px;
  height: 18px;
}
.Switch--small .Switch-slider::before {
  width: 12px;
  height: 12px;
}
.Switch--small input:checked + .Switch-slider::before {
  transform: translateX(16px);
}

/* Large */
.Switch--large .Switch-slider {
  width: 54px;
  height: 30px;
}
.Switch--large .Switch-slider::before {
  width: 24px;
  height: 24px;
}
.Switch--large input:checked + .Switch-slider::before {
  transform: translateX(24px);
}

/* Label layout */
.Switch-label {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  cursor: pointer;
}

.Switch-label-text {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
}

Accessibility

  • Switches use native <input type="checkbox"> for full accessibility
  • Labels are clickable to toggle the switch
  • Keyboard accessible (Space to toggle when focused)
  • Screen readers announce the checked state
  • Use aria-describedby to associate helper text with the switch

Keyboard Support

Key Action
Space Toggle the switch on/off
Tab Move focus to/from the switch

Best Practices

Do

  • Use for binary settings — On/off, enabled/disabled
  • Show immediate effect — Changes apply instantly, no submit button
  • Provide clear labels — Describe what the switch controls
  • Keep labels positive — “Enable notifications” not “Disable notifications”
  • Group related switches — Settings panels with logical grouping
  • Use appropriate sizes — Small for dense UIs, large for touch targets

Don’t

  • Use for forms requiring submission — Use checkboxes instead
  • Hide the current state — Always make it clear what on/off means
  • Use for multiple selections — Switches are single binary choices
  • Use without labels — Every switch needs a text label
  • Mix sizes in a group — Keep sizes consistent within a section
  • Use negative labels — Avoid “Disable dark mode” phrasing