Switch

A control that allows the user to toggle between checked and not checked.

<script setup lang="ts">
import { Label } from '@/components/ui/label'
import { Switch } from '@/components/ui/switch'
</script>

<template>
  <div class="flex items-center space-x-2">
    <Switch id="airplane-mode" />
    <Label for="airplane-mode">Airplane Mode</Label>
  </div>
</template>

Installation

Install the packages

npm install @animate-ui/vue motion-v
pnpm add @animate-ui/vue motion-v
yarn add @animate-ui/vue motion-v
bun add @animate-ui/vue motion-v

Add the shadcn-vue component

npx shadcn-vue@latest add switch
pnpm dlx shadcn-vue@latest add switch
yarn dlx shadcn-vue@latest add switch
bun x shadcn-vue@latest add switch

Animate it

The CLI finds your shadcn-vue components through components.json, swaps their primitive imports for Animate UI's and removes the CSS animation classes Motion replaces.

npx @animate-ui/cli@latest animate switch
pnpm dlx @animate-ui/cli@latest animate switch
yarn dlx @animate-ui/cli@latest animate switch
bun x @animate-ui/cli@latest animate switch

Usage

<script setup lang="ts">
import { SwitchRoot, SwitchThumb } from '@animate-ui/vue/primitives/reka-ui';
</script>

<template>
  <SwitchRoot id="airplane-mode">
    <SwitchThumb />
  </SwitchRoot>
</template>

Animation

The motion of Animate UI's React switch:

  • Thumb, pressed: stretches toward the middle of the track, its other edge in place. Its width grows by 3/16 (a 16px thumb becomes 19px) on a spring (stiffness 300, damping 25). It's the thumb's real width, so its round ends stay round.
  • Thumb, on a change: springs to its new side while its width springs back, on the same spring. The thumb's translate classes still decide where it rests (data-[state=checked]:translate-x-…): Animate UI puts it back where it was with a transform and springs it to its new place.
  • Root doesn't move, and its track changes colour at once: shadcn-vue's transition-all on the track would fade it, so the CLI removes it.
  • The press is the pointer, or Enter on the keyboard. Space toggles without the stretch, and the thumb glides the same way.
  • Toggling again mid-glide turns back from where the thumb is, without a jump.
  • Under reduced motion, the thumb jumps to its side, without the stretch.
  • shadcn-vue's transition-transform on the thumb would tween its translate; the CLI removes it too (Animate UI also skips it while measuring, so a leftover class doesn't break the glide).

API Reference

Every part takes exactly the props of reka-ui's Switch. Animate UI adds the animation props below. With as-child, a part renders your element with reka-ui's behaviour: an as-child SwitchRoot has no press stretch, an as-child SwitchThumb no animation.

SwitchRoot

reka-ui props. The root doesn't animate itself: it tells the thumb when it's pressed.

SwitchThumb

reka-ui props, plus:

PropTypeDefault
transition?
Transition{ type: 'spring', stiffness: 300, damping: 25 }

AnimateUIProvider's tempo scales the spring with everything else.

Built by Skyleen. The source code is available on GitHub.

Last updated: 10/23/2026