Theme
Sound
Jump to a component
Core · Actions
Switch
Switch turns one thing on or off, with its name as the label (the visible text sits beside it). on is the state; disabled greys it.
Live, from @anicanon/sakuga 2.0.0
Sakuga for iOS and Android is coming
iOS
Coming soon
Switch for iOS is in the roughs. The tokens it will read are the ones on this page, the same on every platform.
Android
Coming soon
Switch for Android is in the roughs. The tokens it will read are the ones on this page, the same on every platform.
- Use it for
- One setting that takes effect the moment it changes: Loop this track, Name who speaks.
- Not for
- A choice between named optionsSegmentedControl
- A value on a rangeSliderRow
- Choosing things to act on together, or agreeing to termsCheckbox
Guidelines
- Use it for a setting that takes effect at once (Lower the music under voices, Name who speaks, Loop this track).
- A choice between named options is a
SegmentedControl, not a switch. - The thumb crosses the track on
motion-fastand stretches while held. - With sound on, turning it on or off plays the on or off sound, by press, key or slide (README · Sound).
showLabelsets the label beside it, the whole row toggling: the settings row of a panel (Loops without a seam).hintis a quiet line under the label saying what the setting does; a child sits at the row's end, before the switch (the audio's language).
- With
onChange, the knob can be slid along its track; let go past the middle and the switch is on. A press still flips it.
import { useState } from 'react';
import { Switch } from '@anicanon/sakuga/ui';
export default function SwitchExample() {
const [on, setOn] = useState(true);
const [on2, setOn2] = useState(false);
return (
<>
<Switch on={on} onChange={setOn} label="Name who speaks" />
<Switch on={on2} onChange={setOn2} label="Loop this track" />
<Switch on disabled label="Locked" />
</>
);
}PropsSwitchProps
labelrequiredstringThe setting's name, read by screen readers.
onbooleanshowLabelbooleanSets the label beside it; the whole row toggles.
hintstringWith showLabel: a quiet line under the label.
disabledbooleanonChange(on: boolean) => voidchildrenReactNodeWith showLabel: sits at the row's end, before the switch.
classNamestringEach token reads a role, and the role lands on a value in each theme. Change the role and every component that reads it follows.
Colour
switchrow-fgSwitch with its label shown: the label.text-primaryneutral-925#0b0a10text-primaryneutral-0#ffffffSpace and shape
switch-widthits own value
40px
switch-heightits own value
24px
switch-radiusradius-full9999px
switch-after-insetinset-2xs2px
switch-after-sizeits own value
calc(24px - 2 * 2px)
switch-after-radiusradius-full9999px
switch-after-on-translate-xits own value
calc(40px - calc(var(--switch-height) - 2 * var(--switch-after-inset)) - 2 * 2px)
switch-after-active-scale-xits own value
1.22
switch-after-on-active-translate-xits own value
calc(calc(var(--switch-width) - var(--switch-after-size) - 2 * var(--switch-after-inset)) - calc(var(--switch-height) - 2 * var(--switch-after-inset)) * (1.22 - 1))
switch-after-on-active-scale-xits own value
1.22
switch-disabled-opacityopacity-disabled0.35
switch-edge-widthline-strong2px
switchrow-gapgap-lg12px
switchrow-words-gapgap-2xs2px
switchrow-hint-padding-yinset-md12px
switchrow-hint-border-bottom-widthline-hairline1px
switchrow-end-gapgap-lg12px
Type
switchrow-fonttext-caption500 13px/18px "Funnel Sans", system-ui, -apple-system, "Segoe UI", sans-serif
switchrow-hint-font-weighttext-label-weight600
switchrow-hint-font-sizetext-label-size14px
Aa
switchrow-hint-line-heighttext-label-line-height20px
switchrow-words-small-fonttext-caption500 13px/18px "Funnel Sans", system-ui, -apple-system, "Segoe UI", sans-serif
Motion
switch-durationmotion-fast160ms
switch-easingease-standardcubic-bezier(0.2, 0, 0, 1)
switch-after-durationmotion-fast160ms
switch-after-easingease-standardcubic-bezier(0.2, 0, 0, 1)
switch-after-active-durationmotion-instant100ms
Checked automatically with axe-core 4.11.4 against WCAG 2.2 A and AA, on the live preview above, in light and dark, on 26 October 2026.
- Result
- No issues found, in light or in dark.
- By design
- A switch named by
labelthat Tab reaches; Enter or Space flips it throughonChange, it is announced "on" or "off", anddisabledtakes it out of the tab order. WithshowLabelthe whole row is its label, so a click on the text flips it too, and thehintis its description. Sliding the knob is for the pointer; Enter or Space does the same. In forced colours the track draws an edge and the knob a solid in the system colours (Highlight when on), and the switch keeps its size. - Not tested
- The automated check doesn't test keyboard use, focus order or what a screen reader says. The lines above are the design system's own account of them.