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.