Beta, expect API change, and bugs. Hit one? Tell us.

Skip to content

Switch

An on/off form control.

<script setup lang="ts">
import { Switch } from '@shardsui/vue/switch'
</script>

<template>
  <label class="flex items-center gap-2 text-sm font-normal text-gray-900 select-none">
    <Switch.Root
      checked
      class="flex h-5 w-9 rounded-md bg-gray-300 p-px inset-shadow-xs outline-offset-2 outline-gray-950 transition-colors duration-150 focus-visible:outline-2 data-checked:bg-emerald-600"
    >
      <Switch.Thumb
        class="aspect-square h-full rounded-[calc(var(--radius-md)-1px)] bg-white shadow-sm transition-transform duration-150 data-checked:translate-x-4"
      />
    </Switch.Root>

    Autoplay
  </label>
</template>

Anatomy

<script setup>
import { Switch } from '@shardsui/vue/switch'
</script>

<template>
  <Switch.Root>
    <Switch.Thumb />
  </Switch.Root>
</template>

Usage guidelines

  • Form controls must have an accessible name: provide a wrapping <label> (recommended), an aria-label, or use the Field component. See Labeling a switch.

Examples

Labeling a switch

The simplest way to name a switch is to wrap it in a <label>:

<template>
  <label>
    <Switch.Root>
      <Switch.Thumb />
    </Switch.Root>
    Autoplay
  </label>
</template>

Switch.Root renders a <span> by default so the wrapping <label> toggles the hidden <input type="checkbox"> natively.

Rendering as a native button

When you point a separate label at the switch with for/id instead of wrapping it, render it as a native button with as="button":

<template>
  <div>
    <label for="wifi-switch">Wi-Fi</label>
    <Switch.Root id="wifi-switch" as="button">
      <Switch.Thumb />
    </Switch.Root>
  </div>
</template>

Form integration

Field wires the label and form association:

<template>
  <Form>
    <Field.Root name="autoplay">
      <Field.Label>
        <Switch.Root>
          <Switch.Thumb />
        </Switch.Root>
        Autoplay
      </Field.Label>
    </Field.Root>
  </Form>
</template>

When wrapped in Field.Root, toggling the switch runs the field's validation.

API reference

Root

Represents the switch itself. Renders a <span> element and a hidden <input> beside.

PropTypeDefault
AttributeDescription
data-checkedPresent when the switch is on.
data-uncheckedPresent when the switch is off.
data-disabledPresent when disabled.
data-readonlyPresent when read-only.
data-requiredPresent when required.
data-validPresent when the field is valid (when wrapped in Field.Root).
data-invalidPresent when the field is invalid (when wrapped in Field.Root).
data-touchedPresent when the field has been touched (when wrapped in Field.Root).
data-dirtyPresent when the value has changed (when wrapped in Field.Root).
data-filledPresent when checked (when wrapped in Field.Root).
data-focusedPresent when focused (when wrapped in Field.Root).

Thumb

The movable part that indicates whether the switch is on or off. Renders a <span> element.

PropTypeDefault
AttributeDescription
data-checkedPresent when the switch is on.
data-uncheckedPresent when the switch is off.
data-disabledPresent when disabled.
data-readonlyPresent when read-only.
data-requiredPresent when required.
data-validPresent when the field is valid (when wrapped in Field.Root).
data-invalidPresent when the field is invalid (when wrapped in Field.Root).
data-touchedPresent when the field has been touched (when wrapped in Field.Root).
data-dirtyPresent when the value has changed (when wrapped in Field.Root).
data-filledPresent when checked (when wrapped in Field.Root).
data-focusedPresent when focused (when wrapped in Field.Root).