fix(router): Scroll restoration should use instant scroll behavior for traversals (#64299)

When the scroll position is being restored, this change upates the
behavior to use 'instant' rather than the default 'auto', which will
be whatever the browser behavior is for 'window.scrollTo'. The 'smooth'
behavior does not match how browsers behavior when performing a
traversal navigation for MPAs, which is 'instant'.

related to #58258

PR Close #64299
This commit is contained in:
Andrew Scott 2025-10-06 11:28:49 -07:00 committed by Andrew Kushnir
parent 3c9ed3d529
commit e1da41ffdf
2 changed files with 7 additions and 4 deletions

View file

@ -85,12 +85,13 @@ export class RouterScroller implements OnDestroy {
private consumeScrollEvents() {
return this.transitions.events.subscribe((e) => {
if (!(e instanceof Scroll)) return;
const instantScroll: ScrollOptions = {behavior: 'instant'};
// a popstate event. The pop state event will always ignore anchor scrolling.
if (e.position) {
if (this.options.scrollPositionRestoration === 'top') {
this.viewportScroller.scrollToPosition([0, 0]);
this.viewportScroller.scrollToPosition([0, 0], instantScroll);
} else if (this.options.scrollPositionRestoration === 'enabled') {
this.viewportScroller.scrollToPosition(e.position);
this.viewportScroller.scrollToPosition(e.position, instantScroll);
}
// imperative navigation "forward"
} else {

View file

@ -96,7 +96,9 @@ describe('RouterScroller', () => {
events.next(new NavigationStart(3, '/a', 'popstate', {navigationId: 1}));
events.next(new NavigationEnd(3, '/a', '/a'));
await nextScrollEvent(events);
expect(viewportScroller.scrollToPosition).toHaveBeenCalledWith([10, 100]);
expect(viewportScroller.scrollToPosition).toHaveBeenCalledWith([10, 100], {
behavior: 'instant',
});
});
});
@ -146,7 +148,7 @@ describe('RouterScroller', () => {
events.next(new NavigationEnd(3, '/a#anchor', '/a#anchor'));
await nextScrollEvent(events);
expect(viewportScroller.scrollToAnchor).not.toHaveBeenCalled();
expect(viewportScroller.scrollToPosition).toHaveBeenCalledWith([0, 0]);
expect(viewportScroller.scrollToPosition).toHaveBeenCalledWith([0, 0], {behavior: 'instant'});
});
});