Phi
Switch
@dicehub/phiv1.0.0-beta.1

Switch

A two-state button that can be either on or off.

<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 / EventTypeDefaultDescription
variant"default" | "neutral""default"Visual variant for the switch.
labelstring-Visible label rendered next to the switch.
default slotunknown-Rich Vue content for the switch label.
labelTooltipstring-Tooltip content displayed next to the label via the Phi Label component.
requiredboolean-When explicitly false, shows (optional) text after the label.
controlFirstbooleantruetrue places the switch before the label; false places the label before the switch.
size"sm" | "base" | "lg""base"Switch size.
checkedboolean-Controlled checked state.
disabledboolean-Disables the switch.
transitioningboolean-Sets aria-busy while the switch is transitioning.
ariaLabelstring-Accessible label fallback. You can also pass native aria-label through $attrs.
idstring-Custom id forwarded to the switch control.
classNamestring-Additional CSS classes applied to the switch control.
$attrsButtonHTMLAttributes-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 / EventTypeDefaultDescription
legendstring-Legend text for the group. For custom styling, omit this prop and use Switch.Legend.
default slotunknown-Child Switch.Item components and optionally a Switch.Legend.
errorstring-Validation message displayed below the group.
descriptionstring-Helper text displayed below the group.
description slotunknown-Rich Vue helper content.
disabledboolean-Disables every item in the group.
controlFirstbooleantruetrue places switches before labels; false places labels before switches.
classNamestring-Additional CSS classes applied to the fieldset.

Switch.Legend

Composable legend sub-component for Switch.Group.

Prop / EventTypeDefaultDescription
default slotunknown-Legend content.
classNamestring-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 / EventTypeDefaultDescription
variant"default" | "neutral""default"Visual variant for this item.
labelstring-Visible label rendered next to the switch.
label slotunknown-Rich label content.
classNamestring-Additional CSS classes applied to the label wrapper.
checkedboolean-Controlled checked state.
disabledboolean-Disables this switch item.
size"sm" | "base" | "lg""base"Switch size.
transitioningboolean-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.