Switch
Use switch with the current published Askr packages.
@askrjs/ui/switch0.0.13@askrjs/themes/switch0.0.13
How to use switch
Switch should use the standard themed surface unless the application is deliberately implementing its own design system on top of @askrjs/ui.
- Import the themed component from @askrjs/themes/components; use @askrjs/ui directly only when building a custom visual system.
- Keep switch labels, state, and application actions visible at the call site instead of styling internal DOM nodes.
- Verify keyboard behavior, focus movement or return, disabled state, and both standard themes.
import { Field, FieldLabel, Switch } from '@askrjs/themes/components';
<Field>
<Switch id="public" checked={isPublic()} onCheckedChange={isPublic.set} />
<FieldLabel for="public">Public project</FieldLabel>
</Field>Purpose
Switch is a binary on/off control that behaves like a checkbox but reads as a toggle — think settings screens where flipping a switch has an immediate effect rather than being one of several fields submitted together. Use it when the choice is genuinely binary and the change should feel instant, not when you need a labeled yes/no inside a longer form (Checkbox usually reads better there).
Install and import
Import the behavior from `@askrjs/ui/switch` and the default appearance from `@askrjs/themes/switch`. Both are real subpath exports of their respective packages, so you never need to reach into the root barrel just to render a switch.
Live examples
The demos cover a plain uncontrolled switch, a controlled one wired to `checked`/`onCheckedChange`, and a disabled state. Each renders as a native `<button>` under the hood, which is worth noticing if you're inspecting the DOM — there's no hidden checkbox unless you also pass `name`.
Anatomy
Implement anatomy at the switch boundary: make inputs visible at the call site, keep cleanup with the work that created it, and render the success, unavailable, and failure states where a user can act on them.
State model
`checked` can be left uncontrolled via `defaultChecked`, or driven externally by passing `checked` alongside `onCheckedChange`. There's no separate internal boolean to fight with: whatever value you supply (or the current default) is exactly what renders, and every interaction routes through `onCheckedChange` before anything changes visually in a controlled setup.
Keyboard and accessibility
Switch renders with `role="switch"` and `aria-checked`, and both Enter and Space toggle it — the exact contract spelled out in the package's `SWITCH_A11Y_CONTRACT`, which mirrors the switch pattern published at w3.org/WAI/ARIA/apg/patterns/switch. When disabled, native `<button disabled>` semantics apply automatically since the default render target is a real button element.
Styling and tokens
The track and thumb are styled through `data-slot` and `data-state` (`checked`/`unchecked`) rather than boolean class toggles, so a themed override can target `[data-state="checked"]` without needing to know which internal class name maps to which state. `data-disabled` is set the same way for the disabled visual treatment.
API
`Switch` accepts `checked`, `defaultChecked`, `onCheckedChange`, `disabled`, `required`, `name`, and `value` — the last two exist specifically for the `asChild=false` case where the component ends up participating in native form submission. When `asChild` is true, `Switch` renders through `Slot` onto your own element instead of a `<button>`, and `type` is not accepted in that mode since there's no native button to type.
Edge cases
Per the package's `FORM_INTEGRATION` contract, a Switch backed by a real `<button>` submits through a hidden `checkbox`-type input with value `"on"` when `name` is set — the same convention native checkboxes use, so existing form-handling code that expects checkbox-style submission keeps working. If you render Switch via `asChild` onto a non-button element, that hidden input and the native `disabled` attribute path are no longer available; you're responsible for equivalent `aria-disabled` handling.
Related pages
If the option is one of several related boolean settings displayed together, compare against Checkbox, which typically reads better in dense lists. For a two-state control that toggles a pressed/unpressed visual rather than a settings value, see Toggle Family instead.