Toggle

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

<script setup lang="ts">
import { TextBoldIcon } from '@hugeicons/core-free-icons'
import { HugeiconsIcon } from '@hugeicons/vue'
import { Toggle } from '@/components/ui/toggle'

withDefaults(defineProps<{ size?: 'default' | 'sm' | 'lg' }>(), {
  size: 'default',
})
</script>

<template>
  <Toggle aria-label="Toggle bold" :size="size">
    <HugeiconsIcon :icon="TextBoldIcon" :stroke-width="2" class="h-4 w-4" />
  </Toggle>
</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 toggle
pnpm dlx shadcn-vue@latest add toggle
yarn dlx shadcn-vue@latest add toggle
bun x shadcn-vue@latest add toggle

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 toggle
pnpm dlx @animate-ui/cli@latest animate toggle
yarn dlx @animate-ui/cli@latest animate toggle
bun x @animate-ui/cli@latest animate toggle

Usage

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

<template>
  <Toggle aria-label="Toggle bold">B</Toggle>
</template>

Animation

The motion of Animate UI's React toggle:

  • Toggle scales to 0.97 while pressed, on Motion's default spring for scale (stiffness 550, damping 30). No hover scale.
  • The press scale runs on the compositor (a transform), so a transition class on the toggle doesn't tween its frames.
  • The on/off colours are the component's CSS (data-[state=on]:bg-accent in shadcn-vue).
  • Toggling with Space changes the state at once.
  • Under reduced motion, there is no press scale.

API Reference

Toggle takes exactly the props of reka-ui's Toggle, plus:

PropTypeDefault
transition?
Transition{ type: 'spring', stiffness: 550, damping: 30, restSpeed: 10 }

With as-child, it renders your element with reka-ui's behaviour, without the animation. AnimateUIProvider's tempo scales these transitions with everything else.

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

Last updated: 10/23/2026