Skip to content
Back to skills

Set Up Motion

ASecurity

Use when adding animation and transitions to a frontend — uses the native View Transitions API for navigation/layout changes and the Motion library (motion/react, formerly Framer Motion) for component enter/exit/gesture animation, with every animation gated behind prefers-reduced-motion.

  • 5 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added October 10, 2026
developmentbashreactvuenodeapifrontendperformance

Works with

  • api

Security analysis

A96/100
  • mediumInstalls packages at runtime which could introduce malicious dependencies

Pro scans all 2 files and shows the line behind each finding

Scanned October 10, 2026

npx -y skills add VelimirMueller/lab-claude-skills --skill set-up-motion --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Set Up Motion?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Set Up Motion
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/velimirmueller-set-up-motion-lab-claude-skills/badge)](https://www.skillsdirectory.com/skills/velimirmueller-set-up-motion-lab-claude-skills)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: set-up-motion
description: Use when adding animation and transitions to a frontend — uses the native View Transitions API for navigation/layout changes and the Motion library (motion/react, formerly Framer Motion) for component enter/exit/gesture animation, with every animation gated behind prefers-reduced-motion.
---

# Set Up Motion

## 1. Audit current state

```bash
cat .claude/stack-profile.md 2>/dev/null || cat ~/.claude/stack-profile.md 2>/dev/null   # frontend.framework, frontend.meta, package_manager
grep -E '"(motion|framer-motion|motion-v|@vueuse/motion)"' package.json 2>/dev/null
grep -rn "startViewTransition\|view-transition-name\|prefers-reduced-motion\|useReducedMotion" src/ 2>/dev/null | head
```

Read `frontend.framework` and `package_manager` (commands use pnpm). `frontend.meta` of `nuxt` ships `motion-v/nuxt` and its own page transitions — prefer those. **Prerequisites:** `@/` alias; pairs with `set-up-routing` (route view-transitions) and `configure-accessibility` (reduced-motion is an a11y requirement, not a nicety).

## 2. Decide what to do
- No motion → full setup.
- Animations present but always-on (ignore reduce-motion) → gate them (step 7) — that's an accessibility bug.

## 3. Detect framework
React → **Motion** (`motion/react`). Vue → **`motion-v`**, the Vue build of Motion (documented on motion.dev; same props, `AnimatePresence`, `MotionConfig`). The View Transitions API is native (no dependency) and works in both. Why: `motion-patterns.md`.

## 4. Install
```bash
pnpm add motion          # React (the package was renamed from framer-motion)
# Vue: pnpm add motion-v
```

## 5. View Transitions for navigation + layout changes

Native, GPU-accelerated, near-zero JS. Wrap any DOM change you want animated:
```ts
// src/utils/withViewTransition.ts
export function withViewTransition(update: () => void | Promise<void>): void {
  const reduce = matchMedia('(prefers-reduced-motion: reduce)').matches;
  if (reduce || !document.startViewTransition) {
    void update();
    return;
  }
  document.startViewTransition(update); // the browser snapshots the new DOM after `update` settles
}
```
The callback must finish the DOM change before it returns or its promise settles. React state updates are batched, so flush them inside: `withViewTransition(() => flushSync(() => setView(next)))`. In Vue, await the DOM: `withViewTransition(async () => { await router.push(to); await nextTick(); })`. React 19.3 also ships a stable `<ViewTransition>` component that animates updates made in a `startTransition` / Suspense reveal without calling the API by hand — prefer it for React state changes; keep this helper for Vue and non-React code.

For routing, let the router drive it: TanStack Router has `defaultViewTransition` on `createRouter` and a `viewTransition` prop on `<Link>`; Vue Router has no built-in hook, so wrap the navigation as above. Name shared elements so they morph between routes:
```css
/* the element that persists across routes */
.hero { view-transition-name: hero; }

@media (prefers-reduced-motion: reduce) {
  ::view-transition-group(*),
  ::view-transition-old(*),
  ::view-transition-new(*) { animation: none !important; }
}
```

## 6. Component animation with Motion (React)

```tsx
// src/main.tsx — once, at the root: every motion component honours the OS setting
import { MotionConfig } from 'motion/react';
// <MotionConfig reducedMotion="user"><App /></MotionConfig>
```
```tsx
import { AnimatePresence, motion } from 'motion/react';

export function Toast({ open, children }: { open: boolean; children: React.ReactNode }) {
  return (
    <AnimatePresence>
      {open && (
        <motion.div
          initial={{ opacity: 0, y: 8 }}
          animate={{ opacity: 1, y: 0 }}
          exit={{ opacity: 0, y: 8 }}
          transition={{ duration: 0.2, ease: 'easeOut' }}
        >
          {children}
        </motion.div>
      )}
    </AnimatePresence>
  );
}
```
Under `reducedMotion="user"` Motion drops the transform (`y`) and layout animation and keeps the opacity fade, so the component carries no reduced-motion branch of its own.
`AnimatePresence` is the reason to reach for Motion — it animates **exit**, which CSS can't do on unmount. Vue: `motion-v`'s `<motion.div>` inside `<AnimatePresence>` (same API, wrap the app in its `MotionConfig`), or Vue's built-in `<Transition>`/`<TransitionGroup>` for simple enter/exit.

## 7. Gate everything behind reduced motion

Three layers, all required:
- **Motion:** `<MotionConfig reducedMotion="user">` at the root (above); `useReducedMotion()` only for custom cases such as stopping autoplay video.
- **Tailwind:** author transitions as `motion-safe:transition` / disable with `motion-reduce:transition-none`.
- **View Transitions:** the `@media (prefers-reduced-motion: reduce)` block (step 5) kills them.

Essential feedback (a spinner) may remain; decorative motion (parallax, large slides) must not.

## 8. Verify
```bash
pnpm dev
```
Animations play normally; with OS "Reduce motion" on, transitions are removed/instant and nothing janks. Check the Performance panel: animated properties stay on the compositor (transform/opacity), no layout thrash.

## References
- ./motion-patterns.md — View-Transitions-vs-Motion, animate-transform-not-layout, reduced-motion, motion-is-feedback, performance budget.
- ../configure-accessibility/SKILL.md — reduced motion as an a11y requirement.
- ../_shared/conventions.md — `@/` alias, `utils/` for the pure `withViewTransition` helper.

Files in this skill

  • SKILL.md5.4 KB
  • motion-patterns.md4.2 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.