Switch (Toggle)

Switches are a pleasant interface for toggling a value between two states, and offer the same semantics and keyboard navigation as native checkbox elements.

To get started, install Headless UI via npm or yarn.

Please note that this library only supports Vue 3.

# npm npm install @headlessui/vue # Yarn yarn add @headlessui/vue

Switches are built using the Switch component, which takes in a ref via the v-model prop. You can toggle your Switch by clicking directly on the component, or by pressing the spacebar while its focused.

Toggling the switch updates your ref to its negated value.

<template> <Switch v-model="enabled" :class="enabled ? 'bg-teal-900' : 'bg-teal-700'" class="relative inline-flex items-center h-6 rounded-full w-11" > <span class="sr-only">Enable notifications</span> <span :class="enabled ? 'translate-x-6' : 'translate-x-1'" class="inline-block w-4 h-4 transform bg-white rounded-full" /> </Switch> </template> <script> import { ref } from 'vue' import { Switch } from '@headlessui/vue' export default { components: { Switch }, setup() { const enabled = ref(false) return { enabled } }, } </script>

By default, a Switch renders a button as well as whatever children you pass into it. This can make it harder to implement certain UIs, since the children will be nested within the button.

In these situations, you can use the SwitchLabel component for more flexibility.

This example demonstrates how to use the SwitchGroup, Switch and SwitchLabel components to render a label as a sibling to the button. Note that SwitchLabel works alongside a Switch component, and they both must be rendered within a parent SwitchGroup component.

<template>
<SwitchGroup>
<div class="flex items-center">
<SwitchLabel class="mr-4">Enable notifications</SwitchLabel>
<Switch v-model="enabled" :class='enabled ? "bg-blue-600" : "bg-gray-200"' class="relative inline-flex items-center h-6 transition-colors rounded-full w-11 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500" > <span :class='enabled ? "translate-x-6" : "translate-x-1"' class="inline-block w-4 h-4 transition-transform transform bg-white rounded-full" /> </Switch> </div>
</SwitchGroup>
</template> <script> import { ref } from 'vue' import { Switch, SwitchGroup, SwitchLabel } from '@headlessui/vue' export default { components: { Switch, SwitchGroup, SwitchLabel }, setup() { const enabled = ref(false) return { enabled } }, } </script>

By default, clicking a SwitchLabel will toggle the Switch, just like labels in native HTML checkboxes do. If you'd like to make the label non-clickable (which you might if it doesn't make sense for your design), you can add a passive prop to the SwitchLabel component:

<template> <SwitchGroup>
<SwitchLabel passive>Enable notifications</SwitchLabel>
<Switch v-model="enabled"> <!-- ... --> </Switch> </SwitchGroup> </template> <script> import { ref } from 'vue' import { Switch, SwitchGroup, SwitchLabel } from '@headlessui/vue' export default { components: { Switch, SwitchGroup, SwitchLabel }, setup() { const enabled = ref(false) return { enabled } }, } </script>

Because Switches are typically always rendered to the DOM (rather than being mounted/unmounted like other components), simple CSS transitions are often enough to animate your Switch:

<template> <Switch v-model="enabled"> <!-- Transition the Switch's knob on state change --> <span
:class="enabled ? 'translate-x-9' : 'translate-x-0'"
class="transition duration-200 ease-in-out transform" />
<!-- ... --> </Switch> </template> <script> import { ref } from 'vue' import { Switch } from '@headlessui/vue' export default { components: { Switch }, setup() { const enabled = ref(false) return { enabled } }, } </script>

By default, the children of a Switch will be used as the label for screen readers. If you're using SwitchLabel, the content of your Switch component will be ignored by assistive technologies.

Clicking a Switch or a SwitchLabel toggles the Switch on and off.

CommandDescription

Space when a Switch is focused

Toggles the Switch

All relevant ARIA attributes are automatically managed.

The main Switch component.

PropDefaultDescription
asbutton
String | Component

The element or component the Switch should render as.

v-model
Boolean

Whether or not the switch is checked.

Slot PropDescription
checked

Boolean

Whether or not the switch is checked.

PropDefaultDescription
aslabel
String | Component

The element or component the SwitchLabel should render as.

passivefalse
Boolean

When true, clicking the label won't toggle the Switch.

PropDefaultDescription
asp
String | Component

The element or component the Switch.Description should render as.

PropDefaultDescription
astemplate
String | Component

The element or component the SwitchGroup should render as.

If you're interested in predesigned component examples using Headless UI and Tailwind CSS, check out Tailwind UI — a collection of beautifully designed and expertly crafted components built by us.

It's a great way to support our work on open-source projects like this and makes it possible for us to improve them and keep them well-maintained.