Skip to main content

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):

TokenValueUse
motion.duration.instant80 msState toggles (checkbox, toggle switch)
motion.duration.fast150 msIcon swap, badge count, tooltip appear
motion.duration.base300 msPanel open/close, modal, card expand
motion.duration.slow500 msPage transitions, list reorder, success
motion.duration.crawl800 msAttract loop transitions (kiosk)
motion.easing.standardcubic-bezier(0.2, 0, 0, 1)Most transitions (Material Design standard)
motion.easing.deceleratecubic-bezier(0, 0, 0.2, 1)Elements entering the screen
motion.easing.acceleratecubic-bezier(0.4, 0, 1, 1)Elements leaving the screen
motion.easing.springcubic-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)

TransitionDurationEasingReduced motion
Route push (navigate forward)300 msDecelerateFade only
Route pop (back)250 msAccelerateFade only
Modal open300 msDecelerateFade only
Modal close200 msAccelerateFade only
Drawer open (right)300 msDecelerateFade only
Drawer close250 msAccelerateFade 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

ContextAnimation
Booking confirmedConfetti burst (canvas-confetti; 2 s; respects reduced-motion)
Room check-in completeCheckmark SVG draws + circle completes (500 ms)
Payment acceptedGreen border pulse (1 cycle, 300 ms)
Task marked done (housekeeping)Row slides out left + subtle haptic (mobile)

5.2 Error

ContextAnimation
Form field validation failField shake (horizontal; 3 cycles; 300 ms total)
Payment declinedCard shake + red border pulse (similar shake)
API error (toast)Toast slides in from top-right (300 ms decelerate)
Kiosk errorFull-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

StateFeedback
Tap / clickScale 0.97 (100 ms) → bounce back (150 ms spring)
LoadingSpinner replaces icon; button width locked
SuccessBrief green flash (300 ms) → returns to default
DisabledNo hover/active feedback

References