Skip to content

feat(dashboard): Week 4 AC 4 - Framer Motion animations + scroll-reactive background#22

Merged
BODMAT merged 9 commits into
developmentfrom
feat/week4-framer-animations
Jun 2, 2026
Merged

feat(dashboard): Week 4 AC 4 - Framer Motion animations + scroll-reactive background#22
BODMAT merged 9 commits into
developmentfrom
feat/week4-framer-animations

Conversation

@BODMAT

@BODMAT BODMAT commented Jun 2, 2026

Copy link
Copy Markdown
Owner

What

Closes Week 4 AC 4 (bonus). Adds Framer Motion animations across all key transitions in the dashboard: scroll-reactive background with timer field + prism wave, directional page transitions, AI report loading panel, modal spring, event feed stagger, nav indicator, toasts, count-up stats, and login entrance.

Changes

Code

  • components/parallax-bg.tsx — orchestrates Two.js WebGL canvas + 2D timer canvas; reads scroll velocity via useVelocity and passes intensity to both layers
  • components/glitch-canvas.tsx — Three.js @react-three/fiber canvas: dark background shader with RGB chromatic dispersion wave that activates on scroll (frameloop="always", dpr=1, powerPreference="low-power")
  • components/timer-field.tsx — 2D canvas overlay: 85 monospace timers drift across viewport; green idle → aggressive red + reverse time + downward parallax on scroll
  • components/page-transition.tsxAnimatePresence mode="wait" + directional slide (x ±36, scale 0.97→1); direction derived via getDerivedStateFromProps pattern (no refs in render)
  • components/smooth-scroll.tsxReactLenis root wrapper, duration: 1.4s expo ease-out
  • app/dashboard/layout.tsx — integrates ParallaxBg + PageTransition; removes bg-bg from wrapper so canvas shows through
  • app/dashboard/reports/report-form.tsxLoadingPanel replaced with scanning bar + dot wave + label; metadata row styled as pill badges
  • app/dashboard/reports/api-key-modal.tsxopen prop + AnimatePresence; backdrop and panel animate independently; spring stiffness:400 damping:28
  • app/dashboard/event-feed.tsxmotion.ul stagger container; first 10 items use hidden→visible variants (50ms stagger); lenis.resize() after each page load
  • app/dashboard/event-card.tsxmotion.article + whileHover scale:1.012
  • app/dashboard/header-nav.tsxlayoutId="nav-pill" shared element slides between active links
  • app/dashboard/mobile-nav.tsxAnimatePresence + motion.div height:0→auto replaces CSS max-h trick
  • app/dashboard/top-sessions.tsxmotion.div progress bars animate width:0→actual% on mount
  • app/dashboard/charts.tsxAnimatePresence fade-in when data replaces skeleton
  • app/dashboard/music/music-client.tsxuseCountUp hook (framer animate()) for Artists/Tracks; metadata as pill badges
  • components/toast.tsxAnimatePresence mode="popLayout" + spring slide-in x:120→0
  • app/login/page.tsx + app/login/login-entrance.tsx — stagger entrance: logo → button, 0.12s apart

Tooling / config

  • package.json — added framer-motion, three, @react-three/fiber, lenis, @types/three; removed unused @react-three/postprocessing, postprocessing
  • app/providers.tsx — wrapped app in <SmoothScroll> (Lenis root)

Docs / plan

  • plans/week4/framer-motion-animations.md — full design rationale, commit plan, AC checklist

Design decisions

  • Timer field over particle network — 85 monospace timers are thematically tied to dev session tracking (WorkTrace's core concept); more "sticky" and unique than generic particles
  • 2D canvas for timers, Three.js only for background — text rendering in Three.js requires textures or complex geometry; native Canvas2D is the right tool; Three.js handles only the GLSL shader wave
  • Scroll-triggered only (velocity > 80 px/s) — glitch/prism/red-timers activate only on deliberate fast scroll, not on slow browsing; avoids looking like a bug
  • frameloop="always" + dpr=1 + powerPreference="low-power" — continuous render needed for the wave animation but kept lightweight; no postprocessing pipeline (removed EffectComposer)
  • lenis.resize() in event-feed — Lenis caches scroll height at init; without explicit resize call after infinite scroll loads new content, wheel stops working
  • getDerivedStateFromProps for page directionreact-hooks/refs lint rule forbids reading refs during render; useState with synchronous setState during render (React's derived-state pattern) gives correct direction at mount time without an extra effect

Verification

  • npx tsc --noEmit (dashboard) — clean
  • npm run lint (dashboard) — clean
  • npm run typecheck (extension) — clean
  • Manual test: background timers visible on all 3 pages; red + parallax on fast scroll; page transitions directional; report loading panel animates; modal spring on open/close; feed cards stagger on first load; nav pill slides; toasts slide in from right; music count-up on range change; login stagger; prefers-reduced-motion disables all animations

Out of scope (future PRs)

  • Scroll-triggered section reveal animations for charts/top-sessions (would need useInView per section)
  • 3D tilt on card hover (react-parallax-tilt)

Closes

  • Week 4 AC 4 (bonus) — Framer Motion animations (docs/Task.md)

@vercel

vercel Bot commented Jun 2, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
worktrace Ready Ready Preview, Comment Jun 2, 2026 5:08pm

@BODMAT BODMAT merged commit fb80bbd into development Jun 2, 2026
4 checks passed
@BODMAT BODMAT deleted the feat/week4-framer-animations branch June 2, 2026 17:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant