Toggle
Turns a setting on or off with immediate effect and persistent state.
Design
Functional preview
Running with stable DS HTML and CSS, without a component JavaScript runtime.
Loading functional preview…
Open the HTML/CSS/JS playground
Anatomy
1
2
3
4
1 Input (
2 Track — CSS background that changes color based on checked state.
3 Thumb — CSS pseudo-element that slides left/right.
4 Content Frame (
.ds-toggle) — styled <input type="checkbox"> with role="switch".2 Track — CSS background that changes color based on checked state.
3 Thumb — CSS pseudo-element that slides left/right.
4 Content Frame (
.ds-toggle__content) — wraps label, description and helper text.
Default
With description and helper text
Sizes
Disabled
States
| State | CSS trigger | Visual change | Token |
|---|---|---|---|
| Off | --- | Neutral track with dark thumb | component.toggle.track.fill.off.default, component.toggle.thumb.fill.off.default |
| Off hover | :hover | Darker neutral track/thumb | component.toggle.track.fill.off.hover, component.toggle.thumb.fill.off.hover |
| On | :checked | Primary track with light thumb | component.toggle.track.fill.on.default, component.toggle.thumb.fill.on.default |
| On hover | :checked:hover | Darker primary track | component.toggle.track.fill.on.hover, component.toggle.thumb.fill.on.hover |
| Focus | :focus-visible | 2px outline ring | component.toggle.focus-ring.radius.default + component.focus-ring.* |
| Disabled | [disabled] | Muted track, thumb and label | component.toggle.track.fill.*.disabled, semantic.content.disabled |
Usage
When to use
- The setting takes effect immediately when turned on or off.
- The current state must remain visible after interaction.
When not to use
- The choice is only applied when a form is submitted; use Checkbox.
- The person must choose one alternative among several; use Radio.
Implementation
- Status
- Stable
- Distribution
- npm package
Installation
npm install ds-tispnpm add ds-tisyarn add ds-tisbun add ds-tisImports
import 'ds-tis/css'Markup
<label class="ds-toggle-label">
<input class="ds-toggle" type="checkbox" role="switch" name="notifications" value="enabled" />
<span class="ds-toggle__content">
<span class="ds-toggle__label">Receber notificações</span>
</span>
</label>Web implementation contract
Token mapping
| Property | Token Component | CSS variable |
|---|---|---|
| target height/gap | component.toggle.target.{height,gap}.* | --ds-toggle-target-* |
| track size | component.toggle.track.{width,height}.* | --ds-toggle-track-* |
| track fill | component.toggle.track.fill.*.* | --ds-toggle-track-fill-* |
| track border | component.toggle.track.border-color.*.* | --ds-toggle-track-border-color-* |
| thumb size/fill | component.toggle.thumb.{size,fill}.* | --ds-toggle-thumb-* |
| focus ring | component.toggle.focus-ring.radius.default + component.focus-ring.* | --ds-focus-ring-* + --ds-toggle-focus-ring-radius-default |
| label/helper/description | component.form-field.* | --ds-form-field-* |
CSS classes
| Class | Description |
|---|---|
ds-toggle | Custom styled switch (native checkbox) |
ds-toggle-label | Control wrapper (wraps track + content) |
ds-toggle--sm | Small size (28x16px) |
ds-toggle--lg | Large size (56x32px) |
ds-toggle__content | Vertical frame stacking label, description, and helper text |
ds-toggle__label | Label text (label/md) |
ds-toggle__description | Multiline description text (body/sm) |
ds-toggle__helper | Helper annotation (caption/sm) |
Accessibility
Keyboard interaction
| Key | Action |
|---|---|
Tab | Moves focus to the toggle |
Space | Toggles on/off |
Enter | Does NOT toggle (standard switch behavior) |
Disabled toggles ([disabled]) are removed from tab order automatically by the browser.
Accessibility
| WCAG criterion | Requirement | Status |
|---|---|---|
| 4.1.2 Name, Role, Value (A) | role="switch" + aria-checked managed by native checkbox | ✓ |
| 2.4.11 Focus Appearance (AA) | Focus ring visible via :focus-visible | ✓ |
| 2.5.8 Target Size min (AA) | Label extends click target beyond the toggle itself | ✓ |
| 1.4.1 Use of Color (A) | Position + color both communicate state (thumb slides left/right) | ✓ |
ARIA attributes summary
role="switch" — required on the checkbox so screen readers announce it as a switch.aria-checked — managed automatically by the native <input type="checkbox">.Textual content must be inside
.ds-toggle__content.
Output responsibility
Preserve native element semantics, accessible names, keyboard behavior, and visible focus.
Validation evidence
Covered by the stable Storybook, public runtime tests when applicable, keyboard scenarios, responsive checks, and Axe.