Toggle

A two-state press button. Outline-neutral at rest, highlight-filled when active.

For collections of toggles in a pill container, see Toggle group.

Press button

Add data-stisla-toggle to a <button class="toggle">. Clicking flips aria-pressed. Listen for stisla:toggle:changed to react.

<button type="button" class="toggle" data-stisla-toggle aria-pressed="true">
  <i data-lucide="bell"></i>
  Notifications on
</button>

Form data

For a toggle whose state submits with a form, use a hidden <input class="toggle-input"> paired with a sibling <label class="toggle">. The browser owns selection, so no JS is needed.

<div>
  <input type="checkbox" class="toggle-input" id="newsletterToggle" name="newsletter" checked>
  <label class="toggle" for="newsletterToggle">
    <i data-lucide="mail"></i>
    Subscribe to newsletter
  </label>
</div>

Sizes

Add .toggle--sm or .toggle--lg to match the .btn size cadence (28 / 36 / 44 px under default density).

<div class="d-flex gap-2 align-items-center">
  <button type="button" class="toggle toggle--sm" data-stisla-toggle aria-pressed="true">Bold</button>
  <button type="button" class="toggle" data-stisla-toggle aria-pressed="true">Bold</button>
  <button type="button" class="toggle toggle--lg" data-stisla-toggle aria-pressed="true">Bold</button>
</div>

Icon-only

Add .toggle--icon-only for a square slot (mirrors .btn--icon-only). Add an aria-label so the affordance is named for assistive tech.

<div class="d-flex gap-2 align-items-center">
  <button type="button" class="toggle toggle--icon-only" data-stisla-toggle aria-pressed="false" aria-label="Bold">
    <i data-lucide="bold"></i>
  </button>
  <button type="button" class="toggle toggle--icon-only" data-stisla-toggle aria-pressed="true" aria-label="Italic">
    <i data-lucide="italic"></i>
  </button>
  <button type="button" class="toggle toggle--icon-only" data-stisla-toggle aria-pressed="false" aria-label="Underline">
    <i data-lucide="underline"></i>
  </button>
</div>

Icon-round

Add .toggle--icon-round alongside .toggle--icon-only for a circular silhouette. Same opt-out as .btn--icon-round. Radius forces 9999px and ignores --st-radius.

<div class="d-flex gap-2 align-items-center">
  <button type="button" class="toggle toggle--icon-only toggle--icon-round" data-stisla-toggle aria-pressed="false" aria-label="Like">
    <i data-lucide="thumbs-up"></i>
  </button>
  <button type="button" class="toggle toggle--icon-only toggle--icon-round" data-stisla-toggle aria-pressed="true" aria-label="Love">
    <i data-lucide="heart"></i>
  </button>
  <button type="button" class="toggle toggle--icon-only toggle--icon-round" data-stisla-toggle aria-pressed="false" aria-label="Star">
    <i data-lucide="star"></i>
  </button>
</div>

Disabled

Native :disabled on the button (or on the paired .toggle-input) dims the chip and blocks pointer events.

<div class="d-flex gap-2 align-items-center">
  <button type="button" class="toggle" data-stisla-toggle aria-pressed="false" disabled>Off, disabled</button>
  <button type="button" class="toggle" data-stisla-toggle aria-pressed="true" disabled>On, disabled</button>
  <input type="checkbox" class="toggle-input" id="toggleDisabledForm" disabled>
  <label class="toggle" for="toggleDisabledForm">Form, disabled</label>
</div>

Customization

Twelve variables retune .toggle. Geometry mirrors .btn. Surface variables follow the interactional trio (rest, accent hover, highlight active). It's the same vocabulary sidebar, list-group, table and pagination use for selected state.

Variable Default Use
--toggle-radius var(--st-toggle-radius, var(--st-radius)) Corner radius.
--toggle-height 2.25rem Raw height; density multiplies once.
--toggle-padding-x calc(0.75rem * var(--st-density)) Horizontal padding.
--toggle-font-size 0.875rem Label size.
--toggle-font-weight 500 Label weight.
--toggle-bg transparent Rest fill.
--toggle-color var(--st-foreground) Rest text color.
--toggle-border-color var(--st-border) Rim color.
--toggle-hover-bg var(--st-accent) Hover fill (transient).
--toggle-active-bg var(--st-highlight) Active fill (persistent).
--toggle-active-color var(--st-highlight-foreground) Active text color.
--toggle-active-border-color var(--toggle-active-bg) Active rim. Default matches the bg so the chip reads as a clean solid fill. Override it for a distinct rim.