Skip to content

Commit 3c77ae3

Browse files
committed
Revert "fix(material/menu): remove dependency on animations module (#30163)"
This reverts commit 4620df1.
1 parent a11b03b commit 3c77ae3

File tree

6 files changed

+83
-166
lines changed

6 files changed

+83
-166
lines changed

src/material/menu/menu-animations.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,6 @@ import {
2020
* Animation duration and timing values are based on:
2121
* https://material.io/guidelines/components/menus.html#menus-usage
2222
* @docs-private
23-
* @deprecated No longer used, will be removed.
24-
* @breaking-change 21.0.0
2523
*/
2624
export const matMenuAnimations: {
2725
readonly transformMenu: AnimationTriggerMetadata;

src/material/menu/menu-trigger.ts

Lines changed: 32 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ import {
4040
} from '@angular/core';
4141
import {normalizePassiveListenerOptions} from '@angular/cdk/platform';
4242
import {merge, Observable, of as observableOf, Subscription} from 'rxjs';
43-
import {filter, take, takeUntil} from 'rxjs/operators';
43+
import {filter, takeUntil} from 'rxjs/operators';
4444
import {MatMenu, MenuCloseReason} from './menu';
4545
import {throwMatMenuRecursiveError} from './menu-errors';
4646
import {MatMenuItem} from './menu-item';
@@ -115,7 +115,6 @@ export class MatMenuTrigger implements AfterContentInit, OnDestroy {
115115
private _closingActionsSubscription = Subscription.EMPTY;
116116
private _hoverSubscription = Subscription.EMPTY;
117117
private _menuCloseSubscription = Subscription.EMPTY;
118-
private _pendingRemoval: Subscription | undefined;
119118

120119
/**
121120
* We're specifically looking for a `MatMenu` here since the generic `MatMenuPanel`
@@ -248,7 +247,6 @@ export class MatMenuTrigger implements AfterContentInit, OnDestroy {
248247
passiveEventListenerOptions,
249248
);
250249

251-
this._pendingRemoval?.unsubscribe();
252250
this._menuCloseSubscription.unsubscribe();
253251
this._closingActionsSubscription.unsubscribe();
254252
this._hoverSubscription.unsubscribe();
@@ -287,39 +285,24 @@ export class MatMenuTrigger implements AfterContentInit, OnDestroy {
287285
return;
288286
}
289287

290-
this._pendingRemoval?.unsubscribe();
291-
const previousTrigger = PANELS_TO_TRIGGERS.get(menu);
292-
PANELS_TO_TRIGGERS.set(menu, this);
293-
294-
// If the same menu is currently attached to another trigger,
295-
// we need to close it so it doesn't end up in a broken state.
296-
if (previousTrigger && previousTrigger !== this) {
297-
previousTrigger.closeMenu();
298-
}
299-
300288
const overlayRef = this._createOverlay(menu);
301289
const overlayConfig = overlayRef.getConfig();
302290
const positionStrategy = overlayConfig.positionStrategy as FlexibleConnectedPositionStrategy;
303291

304292
this._setPosition(menu, positionStrategy);
305293
overlayConfig.hasBackdrop =
306294
menu.hasBackdrop == null ? !this.triggersSubmenu() : menu.hasBackdrop;
295+
overlayRef.attach(this._getPortal(menu));
307296

308-
// We need the `hasAttached` check for the case where the user kicked off a removal animation,
309-
// but re-entered the menu. Re-attaching the same portal will trigger an error otherwise.
310-
if (!overlayRef.hasAttached()) {
311-
overlayRef.attach(this._getPortal(menu));
312-
menu.lazyContent?.attach(this.menuData);
297+
if (menu.lazyContent) {
298+
menu.lazyContent.attach(this.menuData);
313299
}
314300

315301
this._closingActionsSubscription = this._menuClosingActions().subscribe(() => this.closeMenu());
316-
menu.parentMenu = this.triggersSubmenu() ? this._parentMaterialMenu : undefined;
317-
menu.direction = this.dir;
318-
menu.focusFirstItem(this._openedBy || 'program');
319-
this._setIsMenuOpen(true);
302+
this._initMenu(menu);
320303

321304
if (menu instanceof MatMenu) {
322-
menu._setIsOpen(true);
305+
menu._startAnimation();
323306
menu._directDescendantItems.changes.pipe(takeUntil(menu.close)).subscribe(() => {
324307
// Re-adjust the position without locking when the amount of items
325308
// changes so that the overlay is allowed to pick a new optimal position.
@@ -355,28 +338,12 @@ export class MatMenuTrigger implements AfterContentInit, OnDestroy {
355338

356339
/** Closes the menu and does the necessary cleanup. */
357340
private _destroyMenu(reason: MenuCloseReason) {
358-
const overlayRef = this._overlayRef;
359-
const menu = this._menu;
360-
361-
if (!overlayRef || !this.menuOpen) {
341+
if (!this._overlayRef || !this.menuOpen) {
362342
return;
363343
}
364344

365345
this._closingActionsSubscription.unsubscribe();
366-
this._pendingRemoval?.unsubscribe();
367-
368-
// Note that we don't wait for the animation to finish if another trigger took
369-
// over the menu, because the panel will end up empty which looks glitchy.
370-
if (menu instanceof MatMenu && this._ownsMenu(menu)) {
371-
this._pendingRemoval = menu._animationDone.pipe(take(1)).subscribe(() => overlayRef.detach());
372-
menu._setIsOpen(false);
373-
} else {
374-
overlayRef.detach();
375-
}
376-
377-
if (menu && this._ownsMenu(menu)) {
378-
PANELS_TO_TRIGGERS.delete(menu);
379-
}
346+
this._overlayRef.detach();
380347

381348
// Always restore focus if the user is navigating using the keyboard or the menu was opened
382349
// programmatically. We don't restore for non-root triggers, because it can prevent focus
@@ -388,6 +355,30 @@ export class MatMenuTrigger implements AfterContentInit, OnDestroy {
388355

389356
this._openedBy = undefined;
390357
this._setIsMenuOpen(false);
358+
359+
if (this.menu && this._ownsMenu(this.menu)) {
360+
PANELS_TO_TRIGGERS.delete(this.menu);
361+
}
362+
}
363+
364+
/**
365+
* This method sets the menu state to open and focuses the first item if
366+
* the menu was opened via the keyboard.
367+
*/
368+
private _initMenu(menu: MatMenuPanel): void {
369+
const previousTrigger = PANELS_TO_TRIGGERS.get(menu);
370+
371+
// If the same menu is currently attached to another trigger,
372+
// we need to close it so it doesn't end up in a broken state.
373+
if (previousTrigger && previousTrigger !== this) {
374+
previousTrigger.closeMenu();
375+
}
376+
377+
PANELS_TO_TRIGGERS.set(menu, this);
378+
menu.parentMenu = this.triggersSubmenu() ? this._parentMaterialMenu : undefined;
379+
menu.direction = this.dir;
380+
menu.focusFirstItem(this._openedBy || 'program');
381+
this._setIsMenuOpen(true);
391382
}
392383

393384
// set state rather than toggle to support triggers sharing a menu

src/material/menu/menu.html

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,12 @@
33
class="mat-mdc-menu-panel"
44
[id]="panelId"
55
[class]="_classList"
6-
[class.mat-menu-panel-animations-disabled]="_animationsDisabled"
7-
[class.mat-menu-panel-exit-animation]="_panelAnimationState === 'void'"
8-
[class.mat-menu-panel-animating]="_isAnimating"
96
(click)="closed.emit('click')"
7+
[@transformMenu]="_panelAnimationState"
8+
(@transformMenu.start)="_onAnimationStart($event)"
9+
(@transformMenu.done)="_onAnimationDone($event)"
1010
tabindex="-1"
1111
role="menu"
12-
(animationstart)="_onAnimationStart($event.animationName)"
13-
(animationend)="_onAnimationDone($event.animationName)"
14-
(animationcancel)="_onAnimationDone($event.animationName)"
1512
[attr.aria-label]="ariaLabel || null"
1613
[attr.aria-labelledby]="ariaLabelledby || null"
1714
[attr.aria-describedby]="ariaDescribedby || null">

src/material/menu/menu.scss

Lines changed: 1 addition & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -31,33 +31,10 @@ mat-menu {
3131
}
3232
}
3333

34-
@keyframes _mat-menu-enter {
35-
from {
36-
opacity: 0;
37-
transform: scale(0.8);
38-
}
39-
40-
to {
41-
opacity: 1;
42-
transform: none;
43-
}
44-
}
45-
46-
@keyframes _mat-menu-exit {
47-
from {
48-
opacity: 1;
49-
}
50-
51-
to {
52-
opacity: 0;
53-
}
54-
}
55-
5634
.mat-mdc-menu-panel {
5735
@include menu-common.base;
5836
box-sizing: border-box;
5937
outline: 0;
60-
animation: _mat-menu-enter 120ms cubic-bezier(0, 0, 0.2, 1);
6138

6239
@include token-utils.use-tokens(tokens-mat-menu.$prefix, tokens-mat-menu.get-token-slots()) {
6340
@include token-utils.create-token-slot(border-radius, container-shape);
@@ -71,22 +48,14 @@ mat-menu {
7148
// We should clean it up eventually and re-approve all the screenshots.
7249
will-change: transform, opacity;
7350

74-
&.mat-menu-panel-exit-animation {
75-
animation: _mat-menu-exit 100ms 25ms linear forwards;
76-
}
77-
78-
&.mat-menu-panel-animations-disabled {
79-
animation: none;
80-
}
81-
8251
// Prevent users from interacting with the panel while it's animating. Note that
8352
// people won't be able to click through it, because the overlay pane will catch the click.
8453
// This fixes the following issues:
8554
// * Users accidentally opening sub-menus when the `overlapTrigger` option is enabled.
8655
// * Users accidentally tapping on content inside the sub-menu on touch devices, if the
8756
// sub-menu overlaps the trigger. The issue is due to touch devices emulating the
8857
// `mouseenter` event by dispatching it on tap.
89-
&.mat-menu-panel-animating {
58+
&.ng-animating {
9059
pointer-events: none;
9160

9261
// If the same menu is assigned to multiple triggers and the user moves quickly between them

0 commit comments

Comments
 (0)