When to use: multiple elements (or a parent + children) need to animate together based on shared state (open/closed, hovered, selected).
How: define a variants object with named states on the parent; pass the same variant names to children without repeating the target values per child. Motion propagates variant changes down the tree automatically.
Trade-offs: requires all children to be motion components; deeply nested custom-prop-driven variants can get harder to trace than inline animate props for a one-off case.
When to use: a component needs to animate out before unmounting (list item removal, modal close, route change).
How: wrap the conditionally-rendered tree in <AnimatePresence>, give the exiting element a stable key, and define an exit variant/prop.
Trade-offs: only works for direct children of AnimatePresence; conditional rendering logic has to keep the exiting element mounted until Motion signals it's done.
When to use: an element's position or size changes due to a layout shift (reordering, resizing, conditional rendering) and you want it to animate rather than jump.
How: add the layout prop (or layoutId for shared-element transitions across different components) instead of hand-computing FLIP transforms.
Trade-offs: layout animation samples layout every frame during the transition, expensive on very large trees, scope it to the smallest subtree that needs it.
When to use: a list or group of children should animate in sequence rather than simultaneously.
How: set staggerChildren (and optionally delayChildren) on the parent variant's transition, children inherit the offset automatically if they use the same variant names.
Trade-offs: stagger timing is relative to the parent's animation start, not absolute; large lists need a capped/virtualized stagger or the last items lag noticeably.
When to use: a value changes every frame (drag position, scroll offset, cursor tracking) and re-rendering React on every update would be too slow.
How: read/write through useMotionValue/useSpring/useTransform instead of useState; bind the motion value directly to a style prop so updates bypass React's render cycle.
Trade-offs: motion values don't trigger re-renders by default, if other UI needs to react to the value, subscribe explicitly with useMotionValueEvent.
When to use: an element needs to respond to more than one interaction (e.g. drag AND hover AND tap) with different visual states for each.
How: combine whileHover, whileTap, whileDrag, whileFocus on the same motion component, each defines its own target state and Motion resolves the active one.
Trade-offs: overlapping gesture states (e.g. hover while dragging) resolve by gesture priority, verify the resolved behavior matches intent rather than assuming pure layering.
When to use: any animation that should respect the OS-level "reduce motion" accessibility setting.
How: set the reduced-motion policy once via MotionConfig's reducedMotion prop ("user" or "always") instead of checking the media query per-component.
Trade-offs: "always" disables transforms/layout animation globally even for users who didn't request it, only use it when the product genuinely never wants motion.
When to use: any animation running continuously or on a hot path (scroll, drag, per-frame updates).
How: animate transform and opacity wherever possible (compositor-only, no layout/paint), avoid animating width/height/top/left/box-shadow-like properties in loops.
Trade-offs: some effects (e.g. true layout reflow) can't be expressed as transform-only, use the layout prop's FLIP-based approach instead of animating layout properties directly.