Production-ready animation patterns for React / Next.js — button, modal, toast, stagger, page transitions, exit animations, scroll, and layout — built on motion-foundations tokens and springs. USE WHEN implementing a concrete UI animation pattern.
Production-ready animation patterns for React / Next.js — button, modal, toast, stagger, page transitions, exit animations, scroll, and layout — built on motion-foundations tokens and springs. USE WHEN implementing a concrete UI animation pattern.
version
1.0.0
cluster
frontend-web
tags
["motion","animation","ui-patterns"]
category
frontend
author
jeff
Motion Patterns
Copy-paste patterns for the most common UI animation needs.
Every pattern here is built on motion-foundations tokens and springs.
Do not define new duration or easing values here — import them.
When to Activate
Animating a button, card, modal, or toast notification
Building list entrances with stagger
Setting up page transitions in Next.js App Router
Adding entrance or exit animations to conditional content
Implementing scroll-reveal, scroll-linked progress, or sticky story sections
Building expanding cards, accordions, or shared-element transitions
Outputs
This skill produces:
Accessible, SSR-safe animation for all standard UI components
AnimatePresence-wrapped conditional renders with correct exit behavior
Page transition wrapper component for Next.js App Router
Scroll-reveal and scroll-linked patterns using useScroll + useTransform
Layout animation patterns (layout, layoutId) for expanding and crossfading elements
Principles
Every pattern imports from motion-foundations. No raw numbers.
Every conditional render is wrapped in AnimatePresence with a key.
Exit animations are always defined alongside enter animations — never as an afterthought.
layout is used only for small, isolated shifts. Large subtrees get explicit transforms.
Rules
Always wrap conditional renders in AnimatePresence with a key on the direct child. Without a key, exit animations never fire.
Always define exit when defining initial + animate. An animation without an exit is incomplete.
Use mode="wait" on page transitions. Enter must not start until exit completes.
Never use layout on subtrees with more than ~5 children or deeply nested DOM. Use explicit x/y transforms instead.
Stagger interval must stay between 0.05s and 0.10s. Below feels mechanical; above feels sluggish.
A staggered list that enters on mount, handles conditional presence, and
respects reduced motion — combining tokens, springs, AnimatePresence, and
the accessibility hook from motion-foundations:
Token and spring definitions → see motion-foundations
Drag interactions, swipe gestures, reorderable lists → see motion-advanced
Text animations (word/character reveal, counters) → see motion-advanced
SVG path drawing or morphing → see motion-advanced
Custom animation hooks → see motion-advanced
CSS-only transitions not using motion/react
Anti-Patterns
Anti-pattern
Rule violated
Fix
AnimatePresence child missing key
Rule 1
Add stable key to the direct child
initial + animate without exit
Rule 2
Always define all three together
Page transition without mode="wait"
Rule 3
Add mode="wait" to AnimatePresence
layout on a 50-item list
Rule 4
Use mode="popLayout" or explicit transforms
staggerChildren: 0.2 on a 10-item list
Rule 5
Cap at 0.08–0.10
Modal without focus trap
Rule 6
Add focus-trap-react or Radix Dialog
whileInView without viewport={{ once: true }}
Rule 7
Repeating entrances distract, not inform
transition={{ duration: 0.3 }} inline
Rule 8
Use motionTokens.duration.normal
Related Skills
motion-foundations — defines all tokens, springs, the useSafeMotion hook, and SSR guards that every pattern here imports. Must be set up first.
motion-advanced — extends these patterns with drag, gestures, SVG, text, custom hooks, and imperative sequencing. Does not redefine any patterns from this skill.