C10 — Motion & Micro-interaction Library
Scope: Named easing curves, duration scale, choreography patterns: page transitions, list reorder, drag-drop on housekeeping board, success/error feedback, undo countdowns, loading skeletons. Required for "rich UI" feel.
1. Motion tokens
All motion values are design tokens (from DO2-token-pipeline.md):
| Token | Value | Use |
|---|---|---|
motion.duration.instant | 80 ms | State toggles (checkbox, toggle switch) |
motion.duration.fast | 150 ms | Icon swap, badge count, tooltip appear |
motion.duration.base | 300 ms | Panel open/close, modal, card expand |
motion.duration.slow | 500 ms | Page transitions, list reorder, success |
motion.duration.crawl | 800 ms | Attract loop transitions (kiosk) |
motion.easing.standard | cubic-bezier(0.2, 0, 0, 1) | Most transitions (Material Design standard) |
motion.easing.decelerate | cubic-bezier(0, 0, 0.2, 1) | Elements entering the screen |
motion.easing.accelerate | cubic-bezier(0.4, 0, 1, 1) | Elements leaving the screen |
motion.easing.spring | cubic-bezier(0.34, 1.56, 0.64, 1) | Success feedback, bounce |
2. prefers-reduced-motion
All animations check prefers-reduced-motion: reduce. When set:
- Duration collapses to ≤ 50 ms (effectively instant)
- Translate/scale animations replaced with opacity fade
- No looping animations
- No parallax effects
Implementation:
@media (prefers-reduced-motion: reduce) {
* {
animation-duration: 0.01ms !important;
transition-duration: 0.01ms !important;
}
}
Additionally, JS-driven animations check window.matchMedia('(prefers-reduced-motion: reduce)').matches.
3. Page transitions (web)
| Transition | Duration | Easing | Reduced motion |
|---|---|---|---|
| Route push (navigate forward) | 300 ms | Decelerate | Fade only |
| Route pop (back) | 250 ms | Accelerate | Fade only |
| Modal open | 300 ms | Decelerate | Fade only |
| Modal close | 200 ms | Accelerate | Fade only |
| Drawer open (right) | 300 ms | Decelerate | Fade only |
| Drawer close | 250 ms | Accelerate | Fade only |
Page push: New page slides in from right (LTR) / left (RTL) + fades in; old page slides out to left (LTR) / right (RTL) + fades out. Implemented via CSS @keyframes + React Transition Group.
4. List and card interactions
4.1 List item entrance (stagger)
When a list loads, items animate in with a 30 ms stagger between each item:
- Each item: translate Y +16px → 0 + opacity 0 → 1
- Duration: 300 ms decelerate
- Max items to animate: 8 (remainder appear instantly)
4.2 Swipe actions (mobile)
Swipe right/left on list items (reservations, tasks):
- Reveal: action panel slides in with spring easing
- Action tap: row collapses with accelerate easing; row removed from list with layout animation (height 56px → 0)
4.3 Drag-and-drop (housekeeping board)
Drag a room card to a different attendant column:
- Lift: card scales 1 → 1.04 + shadow md → xl (duration: fast)
- Drag: follows cursor with 0 ms lag
- Drop: spring snap to target position (duration: base, spring easing)
- Invalid drop: shake animation (3 cycles, 100 ms each)
- Column drop target: highlight border pulses during drag-over
5. Success / error feedback
5.1 Success
| Context | Animation |
|---|---|
| Booking confirmed | Confetti burst (canvas-confetti; 2 s; respects reduced-motion) |
| Room check-in complete | Checkmark SVG draws + circle completes (500 ms) |
| Payment accepted | Green border pulse (1 cycle, 300 ms) |
| Task marked done (housekeeping) | Row slides out left + subtle haptic (mobile) |
5.2 Error
| Context | Animation |
|---|---|
| Form field validation fail | Field shake (horizontal; 3 cycles; 300 ms total) |
| Payment declined | Card shake + red border pulse (similar shake) |
| API error (toast) | Toast slides in from top-right (300 ms decelerate) |
| Kiosk error | Full-screen overlay fade in (300 ms) |
6. Undo countdown
For destructive actions with undo (e.g., "Cancel reservation" → "Undo" toast):
[Reservation cancelled. Undo (5)] ████████░░ (progress bar drains over 5 s)
- Toast shows countdown timer (5 s default; configurable)
- Progress bar drains (CSS animation; linear easing; respects reduced-motion — just shows static countdown number if reduced-motion)
- "Undo" tap cancels the timeout; action reversed via API
7. Skeleton loading choreography
Skeleton screens (from C3) animate with a shimmer effect:
@keyframes shimmer {
from { background-position: -200% 0; }
to { background-position: 200% 0; }
}
.skeleton {
background: linear-gradient(90deg,
var(--mel-color-surface-alt) 25%,
var(--mel-color-surface-alt-bright) 50%,
var(--mel-color-surface-alt) 75%
);
background-size: 200% 100%;
animation: shimmer 1.5s infinite;
}
Reduced motion: Animation removed; skeleton shows as flat muted color.
8. Button feedback
| State | Feedback |
|---|---|
| Tap / click | Scale 0.97 (100 ms) → bounce back (150 ms spring) |
| Loading | Spinner replaces icon; button width locked |
| Success | Brief green flash (300 ms) → returns to default |
| Disabled | No hover/active feedback |