Switch
Overview
A control that toggles between checked and unchecked states with a sliding thumb and native form integration. Use it for a single binary setting that takes effect immediately (e.g. dark mode, notifications); when the option belongs to a form that needs explicit submission, prefer SCheckbox; when more than one value can be selected, use a checkbox group instead.
Usage
Features
- 🎚
modelValue/defaultValue— controlled and uncontrolled modes backed byuseControllableState - 🅰 Custom values —
trueValue/falseValueaccept booleans, strings, or numbers - ⌨️ Keyboard operable — Enter and Space toggle the switch (native button behavior)
- ♿
role="switch"+aria-checked/data-statedual reflection, axe-clean - 📋 Native form proxy — a visually hidden checkbox input carries
name/required/value - 🎨 6 sizes, 8 colors, and rounded/square shapes via
switchVariants - 🧩
leading/trailing/ default (thumb) slots for labels and icons - ↔ RTL-aware thumb animation driven by
dir
Demos
Basic
Slot
API
Aria Layer
5Switch<T>
Props
| Prop | Type | Default | Description |
|---|---|---|---|
class | ClassValue | — | Additional class names applied to the root element. |
ui | Partial<SwitchUi> | — | Per-slot class overrides for the component. |
color | ThemeColor | — | Theme color of the component. |
size | ThemeSize | — | Visual size of the component. |
shape | SwitchShape | — | Shape of the component. |
controlProps | SwitchControlProps | — | Properties forwarded to the control element. |
thumbProps | SwitchThumbProps | — | Properties forwarded to the thumb element. |
defaultValue | NonNullable<T> | — | The state of the switch when it is initially rendered. Use when you do not need to control its state. |
modelValue | T | — | The controlled state of the switch. Can be bind as `v-model`. |
disabled | boolean | — | When `true`, prevents the user from interacting with the switch. |
value | string | — | The value given as data when submitted with a `name`. |
dir | Direction | — | The direction the switch should animate towards when changing state. |
name | string | — | The name of the field. Submitted with its owning form as part of a name/value pair. |
required | boolean | — | When `true`, indicates that the user must set the value before the owning form can be submitted. |
trueValue | NonNullable<T> | true | The value given as data when submitted with a `name`. |
falseValue | NonNullable<T> | false | The value given as data when submitted with a `name`. |
Emits
| Emit Name | Parameters | Description |
|---|---|---|
update:modelValue | NonNullable<T> | Event handler called when the value of the switch changes. |
Slots
| Slot Name | Parameters | Description |
|---|---|---|
default | SwitchCompactSlotProps<T> | Custom content for the default slot. |
leading | SwitchCompactSlotProps<T> | Custom content for the leading slot. |
trailing | SwitchCompactSlotProps<T> | Custom content for the trailing slot. |
SwitchCompact<T>
Props
| Prop | Type | Default | Description |
|---|---|---|---|
controlProps | SwitchControlProps | — | Properties forwarded to the control element. |
thumbProps | SwitchThumbProps | — | Properties forwarded to the thumb element. |
defaultValue | NonNullable<T> | — | The state of the switch when it is initially rendered. Use when you do not need to control its state. |
modelValue | T | — | The controlled state of the switch. Can be bind as `v-model`. |
disabled | boolean | — | When `true`, prevents the user from interacting with the switch. |
value | string | — | The value given as data when submitted with a `name`. |
dir | Direction | — | The direction the switch should animate towards when changing state. |
name | string | — | The name of the field. Submitted with its owning form as part of a name/value pair. |
required | boolean | — | When `true`, indicates that the user must set the value before the owning form can be submitted. |
trueValue | NonNullable<T> | true | The value given as data when submitted with a `name`. |
falseValue | NonNullable<T> | false | The value given as data when submitted with a `name`. |
Emits
| Emit Name | Parameters | Description |
|---|---|---|
update:modelValue | NonNullable<T> | Event handler called when the value of the switch changes. |
Slots
| Slot Name | Parameters | Description |
|---|---|---|
default | SwitchCompactSlotProps<T> | Custom content for the default slot. |
leading | SwitchCompactSlotProps<T> | Custom content for the leading slot. |
trailing | SwitchCompactSlotProps<T> | Custom content for the trailing slot. |
SwitchControl
Props
| Prop | Type | Default | Description |
|---|---|---|---|
id | string | — | Id of the element |
type | ButtonType | 'button' | The type of the button element. Can be one of 'button', 'submit', or 'reset'. |
disabled | boolean | — | Whether the component is disabled. |
asChild | boolean | — | Change the default rendered element for the one passed as a child, merging their props and behavior. |
as | AsTag | Component | 'div' | The element or component this component should render as. Can be overwrite by `asChild` |
SwitchRoot<T>
Props
| Prop | Type | Default | Description |
|---|---|---|---|
defaultValue | NonNullable<T> | — | The state of the switch when it is initially rendered. Use when you do not need to control its state. |
modelValue | T | — | The controlled state of the switch. Can be bind as `v-model`. |
disabled | boolean | — | When `true`, prevents the user from interacting with the switch. |
value | string | — | The value given as data when submitted with a `name`. |
dir | Direction | — | The direction the switch should animate towards when changing state. |
name | string | — | The name of the field. Submitted with its owning form as part of a name/value pair. |
required | boolean | — | When `true`, indicates that the user must set the value before the owning form can be submitted. |
trueValue | NonNullable<T> | true | The value given as data when submitted with a `name`. |
falseValue | NonNullable<T> | false | The value given as data when submitted with a `name`. |
Emits
| Emit Name | Parameters | Description |
|---|---|---|
update:modelValue | NonNullable<T> | Event handler called when the value of the switch changes. |
SwitchThumb
Props
| Prop | Type | Default | Description |
|---|---|---|---|
asChild | boolean | — | Change the default rendered element for the one passed as a child, merging their props and behavior. |
as | AsTag | Component | 'div' | The element or component this component should render as. Can be overwrite by `asChild` |
Notes
Architecture and benchmark differences
VeanUI builds the switch from Aria SwitchRoot (useControllableState + VisuallyHiddenInput form proxy) → SwitchControl (Button base + role="switch" + aria-checked/data-state, disabled-guarded) → SwitchThumb (Primitive + data-state/data-disabled). SwitchCompact composes root + control + thumb, owns the leading/trailing slots, and generates the control id; the UI wrapper SSwitch only computes variant classes via switchVariants and injects the ui map through provideSwitchUi.
| Capability | VeanUI | Ant Design Switch | Element Plus Switch | Mantine Switch | Naive UI Switch | shadcn Switch |
|---|---|---|---|---|---|---|
| Aria/styled split | ✅ | — | — | — | — | ✅ |
| Controlled/uncontrolled | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| Custom on/off values | ✅ | ✅ | ✅ | — | ✅ | ✅ |
| Leading/trailing slots | ✅ | — | ✅ | ✅ | — | — |
loading state | ➕ | ✅ | ✅ | ✅ | ✅ | — |
Inline label (onLabel/offLabel) | ➕ | — | ✅ | ✅ | — | — |
beforeChange hook | ➕ | — | ✅ | — | — | — |
Form proxy / name submit | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| Axe-clean | ✅ | — | — | — | — | — |
Cautions
- The control is a
<button role="switch">— provide an accessible name viacontrolProps(aria-label) or a visible label when used standalone. trueValue/falseValuemust not be nullish; a runtime guard throws otherwise.- The visually hidden input submits
value(default'on') when checked — it is independent oftrueValue. - The form proxy renders only when
nameis present on aform-classed root; pair it with a native<form>or theSFormintegration.
FAQ
Controlled or uncontrolled?
Pass modelValue with v-model for a controlled value, or defaultValue to let the switch own its state internally. Both are supported via useControllableState.
Can I use non-boolean values?
Yes — set trueValue / falseValue to any string or number (e.g. 'on' / 'off'); aria-checked and data-state reflect the comparison against trueValue.
How do I add a label next to the switch?
Use the leading / trailing slots, or pair a native <label> with the control id.
How does the switch submit its value in a form?
Give the switch a name; inside a form-classed root a visually hidden checkbox input is rendered and carries the submitted value when the switch is checked.