Skip to content

desktop: exit animations for dialogs, menus, popovers, toasts and the fullscreen player - #10

Merged
ingoau merged 2 commits into
mainfrom
claude/youthful-cerf-k0x0uf
Sep 25, 2026
Merged

ingoau merged 2 commits into
mainfrom
claude/youthful-cerf-k0x0uf

Conversation

@ingoau

@ingoau ingoau commented Sep 25, 2026

Copy link
Copy Markdown
Owner

Summary

Every transient surface in the Material 3 Expressive desktop shell had an entrance animation but no exit: React unmounted a closed surface in the same commit that closed it, so dialogs, the command palette, context and select menus, the search and jobs popovers, toasts, the narrow-layout side drawer and the fullscreen player all cut to nothing.

  • lib/presence.ts keeps a closed surface mounted for one exit animation: it swaps fade-in for closing, makes the element inert so it takes no focus, keys or clicks on the way out, and unmounts on animationend. When nothing animates (reduced motion turns every animation off) it unmounts at once; a fallback timeout covers a lost event. A list variant handles toasts, which leave individually and keep their place.
  • Exit keyframes for each surface on the emphasised-accelerate easing (already defined, previously unused), held with forwards so nothing flashes back to full opacity before React removes it. The M3 layer gets matching variants where its entrances differ (menus, the search sheet, the drawer).
  • Side effects (returning focus, closing the Connect picker, leaving OS fullscreen) stay keyed on the live store state, so none of them wait for the animation. The docked side panel still closes instantly, being part of the layout.
  • The three remaining hardcoded transition durations in global.css now use the motion tokens.

Test plan

  • pnpm typecheck, pnpm lint (0 errors; 8 pre-existing warnings), pnpm test (150 passed, incl. new presence.test.ts)
  • pnpm build
  • Under Xvfb: the 27 e2e tests in a11y, keyboard-a11y, keyboard, motion-contrast, palette, panels, playback, undo all pass on the built app
  • New e2e/exit-motion.spec.ts: with exits slowed, each surface is mid-animation and inert right after closing, the shell is live again from the first frame, and under reduced motion a closed surface is gone at once with no animation running

🤖 Generated with Claude Code

https://claude.ai/code/session_01MdqKjaWu5KQu7R1syAi9mp


Generated by Claude Code

Claude and others added 2 commits September 25, 2026 03:44
… fullscreen player

Closed surfaces used to unmount in the same commit that closed them, so
the Material 3 entrance animations had no matching exit: dialogs, the
palette, context and select menus, the search and jobs popovers, toasts,
the narrow-layout drawer and the fullscreen player all cut to nothing.

lib/presence.ts keeps a closed surface mounted for one exit animation:
it swaps `fade-in` for `closing` (the new exit keyframes, on the
emphasised-accelerate easing, held with `forwards`), makes the element
inert so it takes no focus, keys or clicks on the way out, and unmounts
on animationend, at once when nothing animates (reduced motion), or on
a fallback timeout. Focus return, the Connect picker close and leaving
window fullscreen stay keyed on the live state, so none of that waits.
The docked side panel still closes instantly, being part of the layout.

The three hardcoded transition durations left in global.css now use the
motion tokens. exit-motion.spec covers the closing state and the
reduced-motion shortcut; presence.test covers the toast list merge.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MdqKjaWu5KQu7R1syAi9mp
On the CI runner the earlier steps outran the toast's 5 s auto-dismiss,
so the Undo click found it mid-exit and then gone. Check the toast first,
straight after playing, and hover it so the timer is held.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MdqKjaWu5KQu7R1syAi9mp
@ingoau
ingoau merged commit d460a73 into main Sep 25, 2026
4 checks passed
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