# @respeak/lucide-motion-vue
[](https://www.npmjs.com/package/@respeak/lucide-motion-vue)
[](https://www.npmjs.com/package/@respeak/lucide-motion-vue)
[](https://bundlephobia.com/package/@respeak/lucide-motion-vue)
[](https://vuejs.org)
[](https://www.npmjs.com/package/@respeak/lucide-motion-vue)
[](https://respeak-io.github.io/lucide-motion-vue/)
**The largest animated icon library for Vue 3.** 546 Lucide icons across 838 named animation variants — drop-in and tree-shakeable, with a live gallery, variant switcher, and copy-paste snippets.
[](https://respeak-io.github.io/lucide-motion-vue/)
**▶︎ [Live gallery + docs](https://respeak-io.github.io/lucide-motion-vue/)** — hover any icon to preview; click for variants, props, and copy-paste snippets. Built on [Motion for Vue](https://motion.dev/docs/vue), ships a Nuxt module, SSR-safe, fully tree-shakable per icon.
- **546 icons / 838 named variants**, tree-shakable per chunk — one icon, one bundle entry
- **Multiple animations per icon.** ``, ``, ``. Variants can carry materially different motion *and* different element graphs under one component name (e.g. `Sun`'s `default` is the animate-ui sunburst, `alt` is the lucide-animated minimal silhouette — same `` import).
- Ergonomic triggers: `animateOnHover`, `animateOnTap`, `animateOnView`
- Composable `` wrapper drives nested icons via provide/inject
- Bind triggers to an ancestor with `triggerTarget="parent"` / `closest:button` — no markup refactor
- **Nuxt module** with auto-imports — `` works with no per-file imports
- SSR-safe with hydration replay (no flash, no mismatch)
- Full TypeScript types, native Motion loops, `currentColor` styling
- Works standalone (``) or composed (`` over anything)
- **Forge** maintainer tool ([see below](#the-forge--design-new-variants)) generates AI-designed icon animations for review — `pnpm forge`
## Contents
- [Install](#install)
- [Usage](#usage)
- [Collision-safe names](#collision-safe-names)
- [Per-icon subpath imports](#per-icon-subpath-imports)
- [Nuxt module](#nuxt-module)
- [Props](#props)
- [Styling](#styling)
- [`` wrapper](#animateicon-wrapper)
- [Discovering variants (`iconsMeta`)](#discovering-variants-iconsmeta)
- [TypeScript](#typescript)
- [Accessibility](#accessibility)
- [Docs site](#docs-site)
- [The Forge — design new variants](#the-forge--design-new-variants)
- [Changelog](./CHANGELOG.md)
- [Contributing / regenerating icons](#contributing--regenerating-icons)
- [License](#license)
## Install
```bash
pnpm add @respeak/lucide-motion-vue motion-v
```
Peer deps: `vue ^3.3`, `motion-v ^2`.
## Usage
```vue
Align columns
```
### Collision-safe names
If you use this library alongside `lucide-vue-next` (static icons), both export `Heart`. Use the `*Animated` alias to disambiguate:
```ts
import { Heart as StaticHeart } from 'lucide-vue-next'
import { HeartAnimated } from '@respeak/lucide-motion-vue'
```
### Per-icon subpath imports
Every icon is also exposed under `/icons/` for consumers who want guaranteed separate chunks (or whose bundler trips on large barrel files):
```ts
import Heart from '@respeak/lucide-motion-vue/icons/heart'
import BetweenVerticalStart from '@respeak/lucide-motion-vue/icons/between-vertical-start'
```
Tree-shaking works with either import style (package is ESM + `"sideEffects": false`).
## Nuxt module
For Nuxt 3 apps the package ships a module at `@respeak/lucide-motion-vue/nuxt` that auto-registers `` and every icon — no imports needed in your templates.
```ts
// nuxt.config.ts
export default defineNuxtConfig({
modules: ['@respeak/lucide-motion-vue/nuxt'],
})
```
```vue
```
The default naming is **suffixed** (``, ``, …) so the module coexists with `lucide-vue-next`'s static ``, `` without collision — keep both installed and pick per-usage. Override the scheme in `nuxt.config` if you want something shorter:
```ts
export default defineNuxtConfig({
modules: ['@respeak/lucide-motion-vue/nuxt'],
lucideMotion: { prefix: 'M', suffix: '' }, // → ,
})
```
Per-icon tree-shaking is preserved — templates that only reference `` ship one chunk, not the whole library.
## Props
Every icon accepts:
| prop | type | default | description |
|-----------------------|--------------------------|----------|---------------------------------------------------------------|
| `size` | `number` | `28` | Rendered width/height in px. |
| `strokeWidth` | `number` | `2` | SVG stroke width. |
| `animate` | `boolean \| string` | `false` | Programmatic trigger. Pass a variant name to select it. |
| `animateOnHover` | `boolean \| string` | `false` | Play while hovered. |
| `animateOnTap` | `boolean \| string` | `false` | Play while pointer is down. |
| `animateOnView` | `boolean \| string` | `false` | Play when the icon enters the viewport. |
| `animation` | `string` | `default`| Which named variant group to pull from (e.g. `fill`). |
| `persistOnAnimateEnd` | `boolean` | `false` | Keep final state instead of returning to `initial`. |
| `initialOnAnimateEnd` | `boolean` | `false` | Force snap to `initial` when animation ends. |
| `clip` | `boolean` | `false` | Clip the icon's overflow at its bounding box — see below. |
| `triggerTarget` | `'self' \| 'parent' \| \`closest:${string}\`` | `'self'` | Bind hover/tap to an ancestor — see [Migrating existing buttons](#migrating-existing-buttons-triggertarget). |
Available `animation` names are icon-specific and mirror upstream animate-ui — e.g. `Heart` supports `default` and `fill`, `BetweenVerticalStart` supports `default` and `default-loop`, `Link2` supports `default`/`apart`/`unlink`/`link`. See [Discovering variants](#discovering-variants-iconsmeta) for a programmatic way to list them, or browse the docs site in `docs/` (`pnpm docs:dev`).
A few animations deliberately move parts of the icon outside its viewBox — `send`'s plane flies off before returning; `rocket`'s launch variant lifts off and out. Those read correctly only when the overflow is hidden, so they disappear on exit instead of touring around the rest of the page. That's what `clip` is for:
```vue
```
Off by default because other icons (e.g. `link-2`'s burst particles) are designed to render outside their box and would break with clipping on.
Icons that are conceptually infinite (`LoaderCircle`, `Loader`, `LoaderPinwheel`, etc.) bake `repeat: Infinity` into their own variant transitions, so they loop as soon as you trigger them — no prop required. One-shot icons play once per trigger.
## Styling
Icons use `stroke="currentColor"` (and `fill: 'currentColor'` for fill-based variants), so color is driven by the parent's CSS `color` — same pattern as `lucide-vue-next`. Fill-based animations automatically pick up whatever color you set, so the tween stays on-brand.
```vue
```
Width and height can come from the `size` prop *or* CSS. Utility classes (`w-6 h-6`, `size-8`), scoped styles, and inline `style` all land on the inner `