<script setup>
import { ref } from "vue";
import { Switch } from "@dicehub/phi/components/switch";
const checked = ref(false);
</script>
<template>
<Switch v-model:checked="checked" label="Switch" />
</template>Installation
Barrel
import { Switch } from "@dicehub/phi";Granular
import { Switch } from "@dicehub/phi/components/switch";Usage
<script setup>
import { ref } from "vue";
import { Switch } from "@dicehub/phi/components/switch";
const checked = ref(false);
</script>
<template>
<Switch v-model:checked="checked" label="Switch" />
</template>Examples
Off State
Switch in the off state.
<script setup>
import { Switch } from "@dicehub/phi/components/switch";
</script>
<template>
<Switch label="Switch" :checked="false" />
</template>On State
Switch in the on state.
<script setup>
import { Switch } from "@dicehub/phi/components/switch";
</script>
<template>
<Switch label="Switch" :checked="true" />
</template>Disabled
Disabled switches cannot be toggled.
<script setup>
import { Switch } from "@dicehub/phi/components/switch";
</script>
<template>
<Switch label="Disabled" :checked="false" disabled />
</template>Variants
The Switch supports two variants: default (blue when on) and neutral (monochrome). Both use a squircle shape.
<script setup>
import { Switch } from "@dicehub/phi/components/switch";
</script>
<template>
<div class="switch-demo-grid">
<Switch label="Default off" :checked="false" />
<Switch label="Default on" :checked="true" />
<Switch label="Neutral off" variant="neutral" :checked="false" />
<Switch label="Neutral on" variant="neutral" :checked="true" />
</div>
</template>Neutral Variant
The neutral variant uses monochrome colors and a squircle shape, ideal for subtle, less prominent toggles.
<script setup>
import { ref } from "vue";
import { Switch } from "@dicehub/phi/components/switch";
const checked = ref(false);
</script>
<template>
<Switch v-model:checked="checked" label="Neutral switch" variant="neutral" />
</template>Neutral States
Neutral variant in different states.
<script setup>
import { Switch } from "@dicehub/phi/components/switch";
</script>
<template>
<div class="switch-demo-stack">
<Switch label="Neutral off" variant="neutral" :checked="false" />
<Switch label="Neutral on" variant="neutral" :checked="true" />
<Switch label="Neutral disabled" variant="neutral" :checked="false" disabled />
</div>
</template>Sizes
Three sizes available: sm, base (default), and lg.
<script setup>
import { Switch } from "@dicehub/phi/components/switch";
</script>
<template>
<div class="switch-demo-stack">
<Switch label="Small" size="sm" :checked="true" />
<Switch label="Base (default)" size="base" :checked="true" />
<Switch label="Large" size="lg" :checked="true" />
</div>
</template>Custom ID
When a custom id is provided, clicking the label still toggles the switch.
<script setup>
import { ref } from "vue";
import { Switch } from "@dicehub/phi/components/switch";
const checked = ref(false);
</script>
<template>
<Switch id="my-custom-switch" v-model:checked="checked" label="Custom ID" />
</template>Switch Group
Group related switches with Switch.Group. Provides a shared legend, description, and error message for the group.
<script setup>
import { Switch } from "@dicehub/phi/components/switch";
</script>
<template>
<Switch.Group legend="Notification settings">
<Switch.Item label="Email notifications" />
<Switch.Item label="SMS notifications" />
<Switch.Item label="Push notifications" />
</Switch.Group>
</template>Visually Hidden Legend
Use Switch.Legend with class-name="phi-sr-only" to keep the legend accessible while hiding it visually.
<script setup>
import { Switch } from "@dicehub/phi/components/switch";
</script>
<template>
<Switch.Group>
<Switch.Legend class-name="phi-sr-only">Notification settings</Switch.Legend>
<Switch.Item label="Email notifications" />
<Switch.Item label="SMS notifications" />
<Switch.Item label="Push notifications" />
</Switch.Group>
</template>Custom Legend Styling
Switch.Legend accepts className for full control over legend presentation.
<script setup>
import { Switch } from "@dicehub/phi/components/switch";
</script>
<template>
<Switch.Group>
<Switch.Legend class-name="switch-demo-legend-subtle">
Notification settings
</Switch.Legend>
<Switch.Item label="Email notifications" />
<Switch.Item label="SMS notifications" />
<Switch.Item label="Push notifications" />
</Switch.Group>
</template>API Reference
Switch
Individual switch toggle with built-in label.
| Prop / Event | Type | Default | Description |
|---|---|---|---|
variant | "default" | "neutral" | "default" | Visual variant for the switch. |
label | string | - | Visible label rendered next to the switch. |
default slot | unknown | - | Rich Vue content for the switch label. |
labelTooltip | string | - | Tooltip content displayed next to the label via the Phi Label component. |
required | boolean | - | When explicitly false, shows (optional) text after the label. |
controlFirst | boolean | true | true places the switch before the label; false places the label before the switch. |
size | "sm" | "base" | "lg" | "base" | Switch size. |
checked | boolean | - | Controlled checked state. |
disabled | boolean | - | Disables the switch. |
transitioning | boolean | - | Sets aria-busy while the switch is transitioning. |
ariaLabel | string | - | Accessible label fallback. You can also pass native aria-label through $attrs. |
id | string | - | Custom id forwarded to the switch control. |
className | string | - | Additional CSS classes applied to the switch control. |
$attrs | ButtonHTMLAttributes | - | Native button attributes and listeners such as aria-label, name, value, lang, title, and @click are forwarded to the control. |
@update:checked | (checked: boolean) => void | - | v-model:checked update event. |
@checked-change | (details: SwitchCheckedChangeDetails) => void | - | Emitted when the checked state changes. |
Switch.Group
Container for multiple switches with legend, description, and error support.
| Prop / Event | Type | Default | Description |
|---|---|---|---|
legend | string | - | Legend text for the group. For custom styling, omit this prop and use Switch.Legend. |
default slot | unknown | - | Child Switch.Item components and optionally a Switch.Legend. |
error | string | - | Validation message displayed below the group. |
description | string | - | Helper text displayed below the group. |
description slot | unknown | - | Rich Vue helper content. |
disabled | boolean | - | Disables every item in the group. |
controlFirst | boolean | true | true places switches before labels; false places labels before switches. |
className | string | - | Additional CSS classes applied to the fieldset. |
Switch.Legend
Composable legend sub-component for Switch.Group.
| Prop / Event | Type | Default | Description |
|---|---|---|---|
default slot | unknown | - | Legend content. |
className | string | - | Additional CSS classes, for example phi-sr-only to visually hide the legend. Use class-name in Vue templates. |
Switch.Item
Individual switch within Switch.Group.
| Prop / Event | Type | Default | Description |
|---|---|---|---|
variant | "default" | "neutral" | "default" | Visual variant for this item. |
label | string | - | Visible label rendered next to the switch. |
label slot | unknown | - | Rich label content. |
className | string | - | Additional CSS classes applied to the label wrapper. |
checked | boolean | - | Controlled checked state. |
disabled | boolean | - | Disables this switch item. |
size | "sm" | "base" | "lg" | "base" | Switch size. |
transitioning | boolean | - | Sets aria-busy while the switch is transitioning. |
@update:checked | (checked: boolean) => void | - | v-model:checked update event. |
@checked-change | (details: SwitchCheckedChangeDetails) => void | - | Emitted when the checked state changes. |
Accessibility
Switch Semantics
Switch controls render with role="switch" and keep aria-checked synchronized with state.
Keyboard Interaction
The switch control is a button, so Enter and Space toggle it through native button behavior.
Grouping
Switch.Group uses semantic fieldset and legend elements to group related switches.