Skip to content

refactor: replace view transitions with Web Animations in MDL#11371

Merged
web-padawan merged 10 commits intomainfrom
refactor/mdl-web-animations
Mar 23, 2026
Merged

refactor: replace view transitions with Web Animations in MDL#11371
web-padawan merged 10 commits intomainfrom
refactor/mdl-web-animations

Conversation

@web-padawan
Copy link
Member

@web-padawan web-padawan commented Mar 19, 2026

Summary

  • Replace the View Transitions API (document.startViewTransition) with the Web Animations API (element.animate()) for detail panel animations
  • Animation parameters read from CSS custom properties (--_mdl-detail-offscreen, --_mdl-transition-duration, --_mdl-easing)
  • Animations are smoothly interruptible: the detail panel's mid-flight translate is captured via getComputedStyle() before cancelling, then used as the starting keyframe of the new animation — so the panel reverses direction from where it is instead of jumping
  • Replace transitions show old content sliding out simultaneously with new content sliding in via a detail-outgoing slot (old content stays in light DOM for style continuity)
  • Remove SlotStylesMixin dependency — animation styles now live in the shadow DOM stylesheet
  • Fix overlay scroll bug: use preventScroll: true when focusing detail content

Fixes #11342
Fixes #8925 (view transition styles don't work inside shadow roots)
Fixes #9666 ([overflow] attribute eagerly removed during close transition)

Changes

  • CSS: Replaced view transition pseudo-elements with CSS custom properties for animation values. Added --_mdl-detail-offscreen (off-screen translate), --_mdl-transition-duration, --_mdl-easing. CSS handles resting states only (default off-screen translate, has-detailtranslate: none). Duration defaults to 0s, enabled via prefers-reduced-motion: no-preference + :not([no-animation])
  • JS: _startTransition uses element.animate() for all transition types. __animate() reads CSS custom properties and returns animation.finished promise. __endTransition() cancels animations and cleans up. Version counter prevents stale animation callbacks
  • Shadow DOM: Added #detail-outgoing container with <slot name="detail-outgoing"> for simultaneous replace transitions. Old content reassigned to outgoing slot (stays in light DOM)
  • Removed: vaadin-master-detail-layout-transition-base-styles.js, SlotStylesMixin usage, ::view-transition-group rules from Aura theme (dialog, notification, MDL)
  • Tests: Renamed view-transitions.test.jstransitions.test.js, rewritten for Web Animations

Test plan

  • yarn test --group master-detail-layout — 86 tests pass
  • yarn test:snapshots --group master-detail-layout — pass
  • yarn lint:js / yarn lint:css / yarn lint:types — pass
  • Manual: test add/remove/replace transitions in dev page
  • Manual: test interruption (click backdrop during slide-in)
  • Manual: test overlay mode at narrow viewport
  • Manual: test RTL, vertical orientation, prefers-reduced-motion

🤖 Generated with Claude Code

@web-padawan web-padawan force-pushed the refactor/mdl-web-animations branch 10 times, most recently from c9a9922 to af376bf Compare March 19, 2026 11:30
@web-padawan web-padawan requested a review from jouni March 19, 2026 11:37
@web-padawan web-padawan force-pushed the refactor/mdl-web-animations branch 2 times, most recently from fbf8351 to a2b6449 Compare March 19, 2026 14:20
@web-padawan web-padawan requested a review from vursen March 19, 2026 14:27
@sonarqubecloud
Copy link

❌ The last analysis has failed.

See analysis details on SonarQube Cloud

Copy link
Member

@jouni jouni left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The backdrop should have a linear fade-in/out transition.

@web-padawan web-padawan force-pushed the refactor/mdl-web-animations branch 2 times, most recently from af6c078 to 8a429e6 Compare March 23, 2026 09:35
Replace the View Transitions API with the Web Animations API for
master-detail-layout detail panel animations. This fixes two issues:
- View transition styles don't work when MDL is inside a shadow root
- [overflow] attribute eagerly removed when closing details

Uses element.animate() with parameters read from CSS custom properties
(--_detail-offscreen, --_transition-duration, --_transition-easing).
Animations are smoothly interruptible: the mid-flight translate is
captured via getComputedStyle() before cancel, then used as the
starting keyframe of the new animation.

Replace transitions use a #outgoing container (slot="detail-outgoing")
that keeps old content in light DOM. In overlay mode, old and new
content slide simultaneously. In split mode, the outgoing cross-fades
out on top, revealing the incoming underneath.

Uses :is(#detail, #outgoing) to share styles between the two detail
elements. Duration defaults to 0s, enabled to 400ms via
prefers-reduced-motion: no-preference.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@web-padawan web-padawan force-pushed the refactor/mdl-web-animations branch from 8a429e6 to d6de738 Compare March 23, 2026 09:48
web-padawan and others added 3 commits March 23, 2026 14:30
Rename __captureDetailTranslate to __captureDetailState, returning
both translate and opacity. Pass as opts.interrupted so __slide uses
both values as starting keyframes. This prevents an opacity flash
when interrupting a mid-fade animation in split mode.

Also remove redundant __crossFade (dead code — split-mode replace
gets 0ms duration from CSS, and __slide already handles the opacity
fade). Unify replace to always use __slide on the outgoing element.

Read overlay state once in _startTransition and pass via opts.overlay
instead of calling hasAttribute('overflow') in multiple methods.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace nested ternary chains with single-condition expressions:
- !overlay && slideIn ? 0 : 1 (fade in only in split mode)
- !overlay && !slideIn ? 0 : 1 (fade out only in split mode)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Update _startTransition to reference __captureDetailState (renamed
from __captureDetailTranslate). Update __animateTransition opts type
to reflect interrupted/overlay fields replacing the old from string.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Update Detail Animations section to reflect opacity fade in split
mode, split/overlay duration tiers (200ms/300ms), default offscreen
values (30px/100%+30px), and capture of both translate and opacity
for smooth interruption.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The default vertical offscreen was still using the old full-height
value (100% + 30px) instead of the small 30px matching horizontal.
The overlay [overflow] rule also lacked a vertical variant, causing
the detail to slide horizontally in vertical overlay mode.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@sonarqubecloud
Copy link

@web-padawan web-padawan merged commit 437226b into main Mar 23, 2026
10 checks passed
@web-padawan web-padawan deleted the refactor/mdl-web-animations branch March 23, 2026 13:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

3 participants