motion-patterns
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 animating a specific UI element in React or Next.js — button, modal, toast, stagger, page transiti
By affaan-m · 2,951 installs
npx skills add affaan-m/ecc --skill motion-patterns
Source repository · Upstream listing
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
1. Always wrap conditional renders in AnimatePresence with a key on the direct child. Without a key, exit animations never fire.
2. Always define exit when defining initial + animate . An animation without an exit is incomplete.
3. Use mode="wait" on page transitions. Enter must not start until exit completes.
4. Never use layout on subtrees with more than ~5 children or deeply nested DOM. Use explicit x / y transforms instead.
5. Stagger interval must stay between 0.05s and 0.10s . Below feels mechanical; above feels sluggish.
6. Modals must always include: focus trap, Escape key close, scroll lock, role="dialog" , aria modal="true" .
7. Scroll reveals use viewport={{ once: true }} . Repeating on scroll out is distracting, not informative.
8. All token values are imported from motion foundations . No inline numbers.
Decision Guidance
Choosing the right pattern
Situation Pattern
Element appears / disappears AnimatePresence
List of items loading in sequence Stagger variants
Navigating between routes Page transition wrapper
Element changes size in place layout prop
Same element moves across page contexts layoutId
Element enters when scrolled into view whileInView
Value tied to scroll position useScroll + useTransform
When to use mode="wait" vs mode="sync"
Mode Use when
wait Page transitions, content swaps (one at a time)
sync Stacked notifications, list items (overlap is fine)
popLayout Items removed from a reflow list
Core Concepts
AnimatePresence contract
Three things must always be true:
1. AnimatePresence wraps the conditional
2. The direct child has a key
3. The child has an exit prop
Miss any one of these and the exit animation silently fails.
layout vs layoutId
layout — animates the element's own size/position change in place
layoutId — links two separate elements, crossfading between them across renders
Use layout="position" on text inside an expanding container to prevent text reflow from animating.
Code Examples
Button feedback
Stagger list
Modal
Toast stack
Page transition (Next.js App Router)
Scroll reveal
Scroll progress bar
Expanding card
Shared element crossfade
Accordion
End to End Example
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 :
Constraints / Non Goals
This skill does not cover:
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.