Animations
Motion patterns for My Trainer Connect. All animations use motion/react (Framer Motion) with spring physics. CSS keyframe animations and Tailwind animate utilities are never used for custom animations in the app.
Animation Principles
motion/react Only
Always use motion from motion/react. Never use CSS @keyframes, Tailwind animate utilities, or raw CSS transitions for custom animations.
Spring Physics
Springs create natural, organic motion. Configure stiffness and damping instead of duration and easing curves. Springs never feel artificial.
Viewport-Triggered
Entrance animations trigger when elements scroll into view using whileInView. Elements animate once with viewport: { once: true }.
Stagger for Sequences
Groups of elements animate in sequence using staggerChildren: 0.08. Creates a cascading reveal effect that guides the eye through content.
Spring Configurations
AnimatedElement
Page content, cards, sections
MagneticButton
Hover interactions, click feedback
CountingNumber
Animated stats, number reveals
Entrance Animation
Standard Entrance
The default entrance animation for all page content. Combines fade, vertical slide, and blur for a smooth reveal.
<motion.div
initial={{ opacity: 0, y: 24, filter: 'blur(4px)' }}
whileInView={{ opacity: 1, y: 0, filter: 'blur(0px)' }}
viewport={{ once: true }}
transition={{ type: 'spring', stiffness: 50, damping: 20 }}
/>
Stagger Pattern
Sequential Reveal
When multiple elements need to appear together, stagger their entrance to create a cascading reveal. Uses the parent container's staggerChildren property.
<motion.div
initial="hidden"
whileInView="visible"
viewport={{ once: true }}
variants={{
visible: {
transition: { staggerChildren: 0.08 }
}
}}
>
{items.map(item => (
<motion.div
key={item.id}
variants={{
hidden: { opacity: 0, y: 24, filter: 'blur(4px)' },
visible: { opacity: 1, y: 0, filter: 'blur(0px)' }
}}
/>
))}
</motion.div>
Hero Animation Sequence
Sequential Hero Elements
Hero sections animate each element with increasing delays. This creates a reading-order reveal: badge first, then title, subtitle, and CTA buttons.
<AnimatedElement delay={0.1}>
<Badge>New</Badge>
</AnimatedElement>
<AnimatedElement delay={0.2}>
<h1>Title</h1>
</AnimatedElement>
<AnimatedElement delay={0.3}>
<p>Subtitle</p>
</AnimatedElement>
<AnimatedElement delay={0.4}>
<ButtonGroup />
</AnimatedElement>
Find Your Perfect Trainer
Connect with certified personal trainers matched to your goals, preferences, and training style.
Component Transitions
Dialog
Zoom + fade from center. Scale 0.95 to 1, opacity 0 to 1.
Dropdown
Slide down + fade. Translates from y: -4px to 0, with opacity.
Sheet
Slides in from the right edge. Uses spring easing for a natural stop.
Toast
Slides up from the bottom with a subtle scale. Appears from off-screen.
Guidelines
| Context | Animation | Details |
|---|---|---|
| Page loads | Recommended | Viewport-triggered entrance animations. Use whileInView with once: true. Stagger child elements at 0.08s. |
| Route changes | Minimal | Avoid route transition animations. They cause visual jank with SSR hydration. Let content appear instantly. |
| User interactions | Recommended | Springs for hover/click feedback. Use MagneticButton spring (stiffness: 150, damping: 20) for snappy response. |
| Data updates | None | Optimistic updates should be instant. No animation on cache updates or mutation responses. Immediate UI feedback. |
| Overlays (dialog, sheet) | Recommended | Short, eased transitions. Dialog: zoom + fade (~200ms). Sheet: slide from edge (~300ms spring). Toast: slide up (~300ms spring). |
| Loading states | Minimal | Use CSS animate-pulse for skeletons only (this is the one exception to the motion-only rule). Spinner icons use animate-spin. |
-
•
Use
motionfrommotion/reactfor all custom animations -
•
Configure springs with
stiffnessanddamping -
•
Trigger entrance animations with
whileInView -
•
Stagger grouped elements at
0.08sintervals -
•
Use
viewport: { once: true }to animate only on first view
-
•
Use CSS
@keyframesfor custom animations -
•
Use Tailwind animate utilities (
animate-bounce, etc.) except for skeletons/spinners - • Animate route transitions (causes SSR hydration jank)
- • Animate data mutation responses (optimistic updates are instant)
-
•
Use
duration/easewhen springs are more appropriate