Motion & Animation
Motion in Fidus provides feedback, guides attention, and creates smooth transitions. All animations are purposeful, subtle, and respect user preferences for reduced motion.
Motion Principles
1. Purposeful
Every animation serves a purpose: feedback, guidance, or context.
2. Subtle
Animations are quick and understated, not distracting.
3. Consistent
Similar interactions have similar animations across the app.
4. Respectful
Honor prefers-reduced-motion for accessibility.
Timing Functions
We use CSS custom properties for consistent timing curves:
| Token | Value | Usage |
|---|---|---|
| --easing-accelerate | cubic-bezier(0.4, 0, 1, 1) | Elements exiting - starts slow, ends fast |
| --easing-decelerate | cubic-bezier(0, 0, 0.2, 1) | Elements entering - starts fast, ends slow |
| --easing-standard | cubic-bezier(0.4, 0, 0.2, 1) | Smooth transitions - balanced start and end |
Interactive Demos
Click "Animate" to see each easing curve in action:
--easing-acceleratecubic-bezier(0.4, 0, 1, 1)
Elements exiting the screen - starts slow, ends fast
--easing-deceleratecubic-bezier(0, 0, 0.2, 1)
Elements entering the screen - starts fast, ends slow
--easing-standardcubic-bezier(0.4, 0, 0.2, 1)
Elements moving within the screen - smooth start and end
Duration Scale
| Token | Value | Usage |
|---|---|---|
| --duration-fast | 150ms | Hover states, button presses |
| --duration-normal | 250ms | Card dismissals, modals |
| --duration-slow | 350ms | Page transitions, large movements |
Common Animations
Fade In (Appearing)
Used when OpportunityCards or widgets appear on screen:
Hover Lift
Subtle elevation on interactive cards:
Hover Over Me
Hover over this card to see it lift up slightly.
Animation: translateY -2px, shadow sm→md, 150ms ease
Expand/Collapse
Used in DetailCard and collapsible sections:
Trip Details
Click to expand/collapse
Swipe Gestures
OpportunityCards support swipe-to-dismiss on mobile. Try swiping the card below on a touch device, or use Chrome DevTools Device Emulation (F12 → Toggle device toolbar).
Budget Alert
You've spent 85% of your monthly food budget (€425 of €500).
Consider adjusting your spending or reviewing your budget allocation.
Swipe Behavior
Card begins tracking finger position in real-time
Card follows finger with no transition delay - immediate feedback
Card springs back to original position with 150ms ease-out transition
Dismiss animation triggers - card slides out completely (250ms ease-in) and onDismiss callback fires
Loading States
Loading states provide feedback during asynchronous operations. Fidus provides Spinner and Skeleton components for different loading scenarios.
Spinner
Used for short operations where exact progress cannot be tracked:
Sizes
With Context
Skeleton Loader
Used for content loading to show the structure before data arrives:
Text Lines
Card Skeleton (List Item)
Rectangular Block
Implementation Examples
Tailwind CSS Classes
// Hover state
<button className="transition-colors duration-150 hover:bg-primary/90">
// Card appearing
<div className="animate-in fade-in slide-in-from-bottom-2 duration-300">
// Card dismissing (custom)
<div className="transition-all duration-250 opacity-0 translate-x-full">
// Respect reduced motion
<div className="transition-all duration-250 motion-reduce:transition-none">Custom Transitions
// In Tailwind config
module.exports = {
theme: {
extend: {
transitionDuration: {
'150': '150ms',
'250': '250ms',
'400': '400ms',
},
transitionTimingFunction: {
'ease-in': 'cubic-bezier(0.4, 0, 1, 1)',
'ease-out': 'cubic-bezier(0, 0, 0.2, 1)',
'ease-in-out': 'cubic-bezier(0.4, 0, 0.2, 1)',
},
},
},
}Usage Guidelines
When to use motion
- •Providing feedback on user interactions (button presses, form submissions)
- •Guiding user attention to important changes (new opportunity card appears)
- •Creating smooth transitions between states (modal opening, panel expanding)
- •Indicating loading or processing states
- •Enhancing perceived performance (skeleton loaders)
Best practices
- •Keep animations subtle - they should enhance, not distract
- •Match animation direction to element behavior (entering from top exits to top)
- •Use consistent durations from the scale (150ms/250ms/400ms)
- •Test on lower-end devices - animations may feel different
- •Avoid animating multiple elements simultaneously
- •Prefer GPU-accelerated properties (transform, opacity)
- •Always respect user preferences for reduced motion
Accessibility
- •Always respect prefers-reduced-motion media query
- •Use motion-reduce: utilities in Tailwind for reduced motion variants
- •Provide instant state changes (no animation) when reduced motion is preferred
- •Never convey information through motion alone - include text or icons
- •Avoid infinite looping animations (except loading indicators)
Do's and Don'ts
✓ Do
- •Use 150ms for instant feedback (hover, press)
- •Use 250ms for transitions (dismiss, modal)
- •Use 400ms for large movements (page transition)
- •Always respect prefers-reduced-motion
- •Animate transform and opacity for performance
- •Keep animations purposeful and subtle
✗ Don't
- •Use auto-playing animations on page load
- •Create long duration animations (>500ms)
- •Use complex 3D transforms
- •Animate many elements at once
- •Create purely decorative animations
- •Ignore user's reduced motion preference
Accessibility: Reduced Motion
Always respect the prefers-reduced-motion media query. Users who enable this setting should see instant state changes without animations.
@media (prefers-reduced-motion: reduce) {
* {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
}
}Tailwind Implementation
<div className="transition-all duration-250 motion-reduce:transition-none">Performance
GPU-Accelerated Properties
Prefer these properties for smooth 60fps animations:
- •
transform- translate, rotate, scale - •
opacity- fade in/out effects
Avoid Animating
These properties cause layout recalculation (expensive):
- ✗
width,height- Use transform: scale() instead - ✗
top,left,right,bottom- Use transform: translate() instead - ✗
margin,padding- Use transform or opacity
Related Components
Button
Uses motion for hover and press states
Modal
Uses fade and scale animations
ProgressBar
Animated progress indicator
Loading States
Loading animations pattern
OpportunityCard
Card with swipe gestures and transitions
Toast
Slide-in notification animations
Resources
Key Takeaways
- ✅ Use 150ms for instant feedback (hover, press)
- ✅ Use 250ms for transitions (dismiss, modal)
- ✅ Use 400ms for large movements (page transition)
- ✅ Always respect prefers-reduced-motion
- ✅ Animate transform and opacity for performance
- ✅ Keep animations purposeful and subtle