Skip to content

feat: bring save-app motion to the main app - #195

Open
flamboh wants to merge 3 commits into
mainfrom
t3code/improve-main-app-animations
Open

flamboh wants to merge 3 commits into
mainfrom
t3code/improve-main-app-animations

Conversation

@flamboh

@flamboh flamboh commented Sep 4, 2026

Copy link
Copy Markdown
Owner

Note

🤖 Claude Fable 5.1 on behalf of Oliver

ELI5

The main app now moves the way tagium save does: buttons press in, icons crossfade instead of popping, new sidebar rows grow into place and removed albums collapse, and covers settle in when they load. List and layout motion runs on Motion (motion.dev) rather than hand-rolled Web Animations code.

Why

Save shipped a small, consistent motion vocabulary. The main app had none of it, so the two apps felt like different products. The first cut of this PR ported save's hand-rolled row helper and FLIP morph; that plumbing produced two real bugs during review, so it was replaced with Motion, whose presence and layout primitives handle enter, exit, reduced motion and measurement correctly.

Implementation

  • motion added. MotionProvider in AppRoot wraps both apps in LazyMotion (features loaded on demand, domMax for layout animations) and MotionConfig reducedMotion="user".
  • src/lib/motion.tsx holds the shared presets: rowShell and rowContent (a row grows from zero height while its content slides down from under the previous row, and collapses on exit), fadePresence, and the timings.
  • Sidebar tracks and albums enter with those presets; albums also exit through AnimatePresence when deleted. Tracks are enter-only on purpose: a track dragged between albums would otherwise fire an exit in one list and an entrance in the other. A seen-id set keeps remounts silent, and a new album animates as one block with its tracks.
  • The media url entry's hand-rolled FLIP (fixed positioning, manual rect bookkeeping, resize handling) is now a Motion layout animation; the validation shake uses useAnimate.
  • Save's recent downloads and the playlist queue panel use the same presets, so the trimmed sixth download and a dismissed queue now collapse instead of vanishing.
  • Press feedback (active:scale-[0.97]) moved into buttonVariants, so every Button gets it; sidebar track rows opt out because they are drag handles.
  • IconSwap replaces icon ternaries on the theme toggle, dropzone, share copy button, link map switches and the url submit button. Image arrival scale-in on sidebar cover thumbs, the editor cover and shared-page artwork. These stay plain CSS on purpose.
  • The React Doctor waiver for the save app's height animation is gone; no waiver is needed now.
  • urlImportGateway unit tests were migrated from a mocked-hooks harness that called the component as a plain function onto react-test-renderer, matching the neighbouring mounting test.

Review instructions

  1. Upload a few tracks: sidebar rows grow in from the top; existing rows slide down rather than jump. Drag a track into another album: it must not replay the entrance. Delete an album: it collapses.
  2. Import from a url on the landing screen, then watch the entry bar glide from the centre to the bottom of the editor.
  3. Toggle light/dark in the sidebar header: the moon/sun crossfade, page colours still snap.
  4. Drag a file over the landing dropzone: the upload icon crossfades to a music note without the box changing size.
  5. In tagium save (?app=tagium-save), run six downloads: the oldest row collapses out.
  6. With reduced motion enabled in the OS, none of the above should animate.

Verified automatically: typecheck, lint, unit tests, chromium e2e (24 pass), plus browser checks that new rows mount at zero height with a running animation and that the url entry morph runs as a Motion layout transform. Not verified: firefox/webkit e2e, and the look on a real touch device. Known: the pre-existing React Doctor complexity warnings on touched components are line-shifted findings that also exist on main; they are for a separate PR.


Changes written by GPT-5.6 Luna agents via codex exec, designed, reviewed, and verified by Claude Fable 5.1 in t3 code.

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Sep 4, 2026

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Preview URL Updated (UTC)
✅ Deployment successful!
View logs
tagium 8e24639 Commit Preview URL

Branch Preview URL
Sep 05 2026, 07:05 AM

@github-actions

github-actions Bot commented Sep 4, 2026

Copy link
Copy Markdown

React Doctor found 6 new issues in 6 files · 6 warnings · score 92 / 100 (Great) · 8 fixed · vs main

6 warnings

src/features/editor/coverArt.tsx

  • ⚠️ L39 React function has high control-flow complexity no-high-complexity-react-function

src/features/import/PlaylistDownloadQueuePanel.tsx

  • ⚠️ L42 React function has high control-flow complexity no-high-complexity-react-function

src/features/library/AlbumSidebarDnd.tsx

  • ⚠️ L75 React function has high control-flow complexity no-high-complexity-react-function

src/features/library/TagSidebarPanel.tsx

  • ⚠️ L80 React function has high control-flow complexity no-high-complexity-react-function

src/features/share/ShareAlbumDialog.tsx

  • ⚠️ L51 React function has high control-flow complexity no-high-complexity-react-function

src/shared/media-url/MediaUrlEntry.tsx

  • ⚠️ L32 React function has high control-flow complexity no-high-complexity-react-function

Reviewed by React Doctor for commit 8e24639. See inline comments for fixes.

Comment thread src/shared/media-url/MediaUrlEntry.tsx
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