Toggle
An independent React adapter where Ark UI provides the parts and Zag maintains on/off state, focus, keyboard, and form behavior.
Design
Functional preview
Running with the independent Ark UI adapter and Zag behavior.
Loading functional preview…
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.
When to choose this output
Choose this adapter in projects that adopted Ark UI and Zag as their behavioral architecture. Do not import it into the shadcn/Base UI output.
Implementation
- Status
- Beta
- Distribution
- Source adapter
Adapter source
packages/react/src/ark/toggle.jsx
import {
Switch,
SwitchContent,
SwitchControl,
SwitchHiddenInput,
SwitchThumb,
SwitchTitle,
} from '@tis/react/ark/toggle'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 the Ark/Zag switch semantics and validate Space, on/off state, disabled state, a stable accessible label, visible focus, and hidden-input form submission.
Validation evidence
Covered by its independent Storybook output plus browser, responsive, keyboard, Axe, and bundle checks.