From 7c758264ddcec06f49d920be71ca510c76b1607a Mon Sep 17 00:00:00 2001 From: Susan Date: Wed, 29 Jul 2026 15:15:13 +0100 Subject: [PATCH] feat(design-system): add motion duration and easing tokens (Closes #397) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Define fast (150ms), normal (250ms), and slow (400ms) duration tokens - Add ease-smooth and ease-bounce easing function tokens - Document usage for micro-interactions, UI transitions, and page animations - Update landing page pulse animations to consume duration/easing tokens - Implement prefers-reduced-motion to disable non-essential animations - Preserve focus and state change transitions for accessibility Implements DS-010 acceptance criteria: ✓ Fast, normal, and slow duration tokens and two easing tokens exist ✓ Existing landing animations consume the tokens where applicable ✓ prefers-reduced-motion disables non-essential motion ✓ Focus and state changes remain understandable without animation --- apps/web/src/styles/landing.css | 21 +++++++++++++++++++++ apps/web/src/ui/landing/footer.tsx | 5 ++++- apps/web/src/ui/landing/hero.tsx | 5 ++++- packages/ui/src/styles/globals.css | 24 ++++++++++++++++++++++++ 4 files changed, 53 insertions(+), 2 deletions(-) diff --git a/apps/web/src/styles/landing.css b/apps/web/src/styles/landing.css index 0305b1a..df119ab 100644 --- a/apps/web/src/styles/landing.css +++ b/apps/web/src/styles/landing.css @@ -17,6 +17,27 @@ } } +/* Reduced motion: disable non-essential animations while preserving critical state changes */ +@media (prefers-reduced-motion: reduce) { + *, + *::before, + *::after { + animation-duration: 0.01ms !important; + animation-iteration-count: 1 !important; + transition-duration: 0.01ms !important; + } + + /* Preserve focus and state change animations for accessibility */ + :focus, + :focus-visible, + [data-state="open"], + [data-state="closed"], + [aria-expanded="true"], + [aria-expanded="false"] { + transition-duration: var(--duration-fast) !important; + } +} + /* Hero decorative gradients — adapt to primary token in both themes */ .hero-glow::before { content: ""; diff --git a/apps/web/src/ui/landing/footer.tsx b/apps/web/src/ui/landing/footer.tsx index bfb486a..0990dee 100644 --- a/apps/web/src/ui/landing/footer.tsx +++ b/apps/web/src/ui/landing/footer.tsx @@ -162,7 +162,10 @@ export function Footer() { Mainnet · block 84,218,402 diff --git a/apps/web/src/ui/landing/hero.tsx b/apps/web/src/ui/landing/hero.tsx index d10736e..30ca46c 100644 --- a/apps/web/src/ui/landing/hero.tsx +++ b/apps/web/src/ui/landing/hero.tsx @@ -245,7 +245,10 @@ export function Hero() { Mainnet · v1.4 · Lagos UTC+1 diff --git a/packages/ui/src/styles/globals.css b/packages/ui/src/styles/globals.css index e41c6b3..ab495ba 100644 --- a/packages/ui/src/styles/globals.css +++ b/packages/ui/src/styles/globals.css @@ -88,6 +88,30 @@ --radius-2xl: calc(var(--radius) * 1.8); --radius-3xl: calc(var(--radius) * 2.2); --radius-4xl: calc(var(--radius) * 2.6); + + /* + * Motion duration and easing tokens (DS-010). + * + * Standardizes timing for micro-interactions, panel transitions, and page-level animations. + * All motion respects prefers-reduced-motion to ensure accessibility. + * + * Duration scale: + * - fast (150ms): Micro-interactions (hover states, focus rings, tooltips) + * - normal (250ms): Standard UI transitions (dropdowns, modals, tab switches) + * - slow (400ms): Page-level animations (drawer slides, route transitions) + * + * Easing functions: + * - ease-smooth: General purpose for most UI transitions + * - ease-bounce: Playful interactions, attention-grabbing elements + * + * Usage: duration-fast, duration-normal, duration-slow, ease-smooth, ease-bounce + */ + --duration-fast: 150ms; /* Micro-interactions: hover, focus, tooltips */ + --duration-normal: 250ms; /* UI transitions: dropdowns, modals, tabs */ + --duration-slow: 400ms; /* Page animations: drawers, route changes */ + --ease-smooth: cubic-bezier(0.4, 0, 0.2, 1); /* Default easing for smooth transitions */ + --ease-bounce: cubic-bezier(0.68, -0.55, 0.265, 1.55); /* Playful bounce effect */ + --font-sans: 'Geist Variable', sans-serif; /*