mirror of
https://github.com/angular/angular.git
synced 2026-09-14 13:54:52 +08:00
fix(menu): scroll position jumping to top after animation is done on scrollable menu (#14190)
Originally in #11859 we introduced some logic that makes sure that the menu panel is always scrolled to the top when it's open. This works, but is janky, because the user can see the menu being scrolled down while it's animating. These changes move the logic, that reset the scroll position, from the `done` callback to `start`. Fixes #11790.
This commit is contained in:
committed by
Jeremy Elbourn
parent
7ce7797d24
commit
37a7080e00
@@ -384,13 +384,17 @@ export class MatMenu implements AfterContentInit, MatMenuPanel<MatMenuItem>, OnI
|
||||
_onAnimationDone(event: AnimationEvent) {
|
||||
this._animationDone.next(event);
|
||||
this._isAnimating = false;
|
||||
}
|
||||
|
||||
// Scroll the content element to the top once the animation is done. This is necessary, because
|
||||
// we move focus to the first item while it's still being animated, which can throw the browser
|
||||
// off when it determines the scroll position. Alternatively we can move focus when the
|
||||
// animation is done, however moving focus asynchronously will interrupt screen readers
|
||||
// which are in the process of reading out the menu already. We take the `element` from
|
||||
// the `event` since we can't use a `ViewChild` to access the pane.
|
||||
_onAnimationStart(event: AnimationEvent) {
|
||||
this._isAnimating = true;
|
||||
|
||||
// Scroll the content element to the top as soon as the animation starts. This is necessary,
|
||||
// because we move focus to the first item while it's still being animated, which can throw
|
||||
// the browser off when it determines the scroll position. Alternatively we can move focus
|
||||
// when the animation is done, however moving focus asynchronously will interrupt screen
|
||||
// readers which are in the process of reading out the menu already. We take the `element`
|
||||
// from the `event` since we can't use a `ViewChild` to access the pane.
|
||||
if (event.toState === 'enter' && this._keyManager.activeItemIndex === 0) {
|
||||
event.element.scrollTop = 0;
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
(keydown)="_handleKeydown($event)"
|
||||
(click)="closed.emit('click')"
|
||||
[@transformMenu]="_panelAnimationState"
|
||||
(@transformMenu.start)="_isAnimating = true"
|
||||
(@transformMenu.start)="_onAnimationStart($event)"
|
||||
(@transformMenu.done)="_onAnimationDone($event)"
|
||||
tabindex="-1"
|
||||
role="menu">
|
||||
|
||||
Reference in New Issue
Block a user