Tour Dash
Report · 21 August 2026

Motion Polish Pass

Tour Dash's UI shell was stock shadcn/Radix with almost no custom motion work — not over-animated, just under-finished. Ran a proper animation audit against the live codebase (Emil Kowalski's design-engineering method) and shipped the three highest-leverage fixes it surfaced, plus a pass of accessibility gating the rest of the motion was missing.

Scope Animation audit & targeted fixes Status Shipped, verified live
01

What the audit found

Two sweeps ran against the app: one hunting for broken or non-compliant motion already in place, one hunting for places that don't animate but should. Six vetted findings, five additive opportunities. No motion library was in use anywhere — every animation is plain Tailwind/Radix, no Framer Motion or GSAP.

AreaStatusDetail
Button press feedbackFixedEvery button in the app had a hover state and zero :active feedback. Added a single active:scale-[0.97] to the shared Button component — fixes every button on every screen at once.
Sidebar nav indicatorFixedThe active-page accent bar animated height via transition-all — a layout-triggering property paired with the broadest possible transition, firing on every navigation click. Rebuilt on scaleY + opacity.
Withdrawal dialogFixedThe four-step withdraw flow (method → amount → confirm → success) teleported between steps with no transition, and the success checkmark — a rare, high-emotion "money confirmed" moment — rendered flat. Added a slide/fade per step and a scale-in on the success icon.
Reduced motionFixedNot one line of the real app respected prefers-reduced-motion — the only occurrence in the whole codebase was inside a dead, unimported Vite boilerplate file. Added a global rule that drops movement app-wide on every dialog, sheet, dropdown, popover and toast, keeping opacity.
Touch hover-lockFixedThe listing-image preview and map-pin hover-scale effects had no fine-pointer gate, so a tap on the mobile bottom-nav experience could leave them stuck scaled up. Gated both to devices that genuinely support hover.
Motion tokensOpenNo shared easing/duration tokens exist anywhere — durations are ad hoc (default 150ms, 200/300/500ms scattered with no system). Left open; not urgent, but worth consolidating before more motion gets added.
Duplicate toast systemsOpenBoth the Radix-based Toaster and Sonner are mounted simultaneously with two different motion languages. Needs a decision on which one is canonical before removing the other.

Five more opportunities were identified and gated through a strict frequency/purpose/speed/function filter before being logged — empty-state entrances, a stagger on card grids, and a crossfade on loading-spinner → content swaps across a dozen screens. None were implemented this pass; they're additive polish, not fixes to something broken.

02

How it was verified

Not just "it compiled":

Worth flagging separately: the demo credentials shown on the login screen didn't sign in during this pass — worth a look, independent of the motion work.

03

What's next

Two items carried forward from the audit: consolidating motion into shared easing/duration tokens, and deciding which of the two mounted toast systems is canonical. Neither blocks anything — both are cohesion cleanup, not bugs. The five logged opportunities (empty-state entrances, card-grid stagger, loading-to-content crossfades) are available to pick up whenever there's appetite for additive polish rather than fixes.