Skip to content

fix(router): avoid view transitions when the user agent provides one - #70140

Open
SkyZeroZx wants to merge 2 commits into
angular:mainfrom
SkyZeroZx:fix/router-ua-view-transition
Open

fix(router): avoid view transitions when the user agent provides one#70140
SkyZeroZx wants to merge 2 commits into
angular:mainfrom
SkyZeroZx:fix/router-ua-view-transition

Conversation

@SkyZeroZx

Copy link
Copy Markdown
Contributor

Preserve hasUAVisualTransition through Location and the Router navigation pipeline. This prevents withViewTransitions from starting an author transition after the browser has already performed one, including across redirects and when using experimental platform navigation.

References:

Note:

Note: By default Chrome on Android does not offer visual transitions for navigations invoked by a swipe gesture. This feature is in an experimental state and only available behind the chrome://flags/#back-forward-transitions feature flag.

Although the article mentions that swipe gestures are not a default behavior, this is not currently true in Chrome 150 on Android; the feature flag does not exist and it has become the default behavior.

What is the current behavior?

without_skip_router-ua-view-transition.mp4

What is the new behavior?

fixed_router-ua-view-transition.mp4

@pullapprove
pullapprove Bot requested review from atscott and iteriani August 10, 2026 18:38
@angular-robot angular-robot Bot added area: router requires: TGP This PR requires a passing TGP before merging is allowed labels Aug 10, 2026
@ngbot ngbot Bot added this to the Backlog milestone Aug 10, 2026
@pullapprove
pullapprove Bot requested a review from atscott August 14, 2026 19:40

@atscott atscott left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

reviewed-for: public-api

Preserve hasUAVisualTransition through Location and the Router navigation pipeline. This prevents withViewTransitions from starting an author transition after the browser has already performed one, including across redirects and when using experimental platform navigation.

References:

https://html.spec.whatwg.org/multipage/nav-history-apis.html#dom-popstateevent-hasuavisualtransition

https://html.spec.whatwg.org/multipage/nav-history-apis.html#dom-navigateevent-hasuavisualtransition

https://developer.chrome.com/docs/web-platform/view-transitions/same-document#integration-with-the-navigation-api-and-other-frameworks
@atscott
atscott force-pushed the fix/router-ua-view-transition branch from d356c4d to 4f9425e Compare August 14, 2026 19:56
jasmine.objectContaining({
canIntercept: true,
hashChange: false,
hasUAVisualTransition: false,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I suspect this is showing how this is going to be breaking for tests

Comment on lines +203 to +221
const hasUAVisualTransition = event.hasUAVisualTransition === true;
const invokeListener = () => {
listener(
event['url']!,
event.state as RestoredState | null | undefined,
'popstate',
{
replaceUrl: true,
},
hasUAVisualTransition,
);
};

if (hasUAVisualTransition) {
// A UA visual transition has already started. Schedule the navigation immediately so
// the browser can present the post-navigation DOM without an additional task.
invokeListener();
return;
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

We shouldn't bypass setTimeout here for hasUAVisualTransition.

  1. Guards & Resolvers: Router navigations frequently involve asynchronous guards, resolvers, lazy loading, or data fetching, so there is no guarantee that the DOM update can be completed in the current task anyway.
  2. Timing Consistency: Deferring popstate navigations with setTimeout is an established router behavior. Introducing a timing fork where swipe-back gestures execute synchronously but back-button clicks execute in a macrotask adds unnecessary timing discrepancies into the router state machine.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done

@atscott atscott left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

requesting changes for revert of synchronous listener invocation

@SkyZeroZx
SkyZeroZx requested a review from atscott August 14, 2026 20:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: router requires: TGP This PR requires a passing TGP before merging is allowed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants