Skip to content

Commit 342e3c6

Browse files
crisbetotinayuangao
authored andcommitted
fix(expansion-panel,menu,select): nested animations not working (#9134)
Fixes issues with the expansion panel, menu and select animations where the child animations were being blocked by the parent ones. **Note:** the menu animations needed a bit more refactoring since the old approach wasn't very idiomatic and made it harder to run the parallel animations. Fixes #8814. Fixes #8953.
1 parent 3b5a441 commit 342e3c6

File tree

6 files changed

+48
-31
lines changed

6 files changed

+48
-31
lines changed

src/lib/expansion/expansion-animations.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,13 @@
77
*/
88
import {
99
animate,
10+
animateChild,
11+
group,
1012
state,
1113
style,
1214
transition,
1315
trigger,
16+
query,
1417
AnimationTriggerMetadata,
1518
} from '@angular/animations';
1619

@@ -42,7 +45,10 @@ export const matExpansionAnimations: {
4245
}), {
4346
params: {expandedHeight: '64px'}
4447
}),
45-
transition('expanded <=> collapsed', animate(EXPANSION_PANEL_ANIMATION_TIMING)),
48+
transition('expanded <=> collapsed', group([
49+
query('@indicatorRotate', animateChild(), {optional: true}),
50+
animate(EXPANSION_PANEL_ANIMATION_TIMING),
51+
])),
4652
]),
4753

4854
/** Animation that expands and collapses the panel content. */

src/lib/menu/menu-animations.ts

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ import{
1212
style,
1313
animate,
1414
transition,
15+
query,
16+
group,
17+
sequence,
1518
AnimationTriggerMetadata,
1619
} from '@angular/animations';
1720

@@ -33,22 +36,22 @@ export const matMenuAnimations: {
3336
* delay to display the ripple.
3437
*/
3538
transformMenu: trigger('transformMenu', [
36-
// TODO(kara): switch to :enter and :leave once Mobile Safari is sorted out.
3739
state('void', style({
3840
opacity: 0,
3941
// This starts off from 0.01, instead of 0, because there's an issue in the Angular animations
4042
// as of 4.2, which causes the animation to be skipped if it starts from 0.
4143
transform: 'scale(0.01, 0.01)'
4244
})),
43-
state('enter-start', style({
44-
opacity: 1,
45-
transform: 'scale(1, 0.5)'
46-
})),
47-
state('enter', style({
48-
transform: 'scale(1, 1)'
49-
})),
50-
transition('void => enter-start', animate('100ms linear')),
51-
transition('enter-start => enter', animate('300ms cubic-bezier(0.25, 0.8, 0.25, 1)')),
45+
transition('void => enter', sequence([
46+
query('.mat-menu-content', style({opacity: 0})),
47+
animate('100ms linear', style({opacity: 1, transform: 'scale(1, 0.5)'})),
48+
group([
49+
query('.mat-menu-content', animate('400ms cubic-bezier(0.55, 0, 0.55, 0.2)',
50+
style({opacity: 1})
51+
)),
52+
animate('300ms cubic-bezier(0.25, 0.8, 0.25, 1)', style({transform: 'scale(1, 1)'})),
53+
])
54+
])),
5255
transition('* => void', animate('150ms 50ms linear', style({opacity: 0})))
5356
]),
5457

@@ -58,6 +61,8 @@ export const matMenuAnimations: {
5861
* after its containing element is scaled in.
5962
*/
6063
fadeInItems: trigger('fadeInItems', [
64+
// TODO(crisbeto): this is inside the `transformMenu`
65+
// now. Remove next time we do breaking changes.
6166
state('showing', style({opacity: 1})),
6267
transition('void => *', [
6368
style({opacity: 0}),

src/lib/menu/menu-directive.ts

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
* found in the LICENSE file at https://angular.io/license
77
*/
88

9-
import {AnimationEvent} from '@angular/animations';
109
import {FocusKeyManager} from '@angular/cdk/a11y';
1110
import {Direction} from '@angular/cdk/bidi';
1211
import {ESCAPE, LEFT_ARROW, RIGHT_ARROW} from '@angular/cdk/keycodes';
@@ -31,6 +30,7 @@ import {
3130
ViewChild,
3231
ViewEncapsulation,
3332
NgZone,
33+
OnInit,
3434
} from '@angular/core';
3535
import {Observable} from 'rxjs/Observable';
3636
import {merge} from 'rxjs/observable/merge';
@@ -82,7 +82,7 @@ const MAT_MENU_BASE_ELEVATION = 2;
8282
],
8383
exportAs: 'matMenu'
8484
})
85-
export class MatMenu implements AfterContentInit, MatMenuPanel, OnDestroy {
85+
export class MatMenu implements OnInit, AfterContentInit, MatMenuPanel, OnDestroy {
8686
private _keyManager: FocusKeyManager<MatMenuItem>;
8787
private _xPosition: MenuPositionX = this._defaultOptions.xPosition;
8888
private _yPosition: MenuPositionY = this._defaultOptions.yPosition;
@@ -95,7 +95,7 @@ export class MatMenu implements AfterContentInit, MatMenuPanel, OnDestroy {
9595
_classList: {[key: string]: boolean} = {};
9696

9797
/** Current state of the panel animation. */
98-
_panelAnimationState: 'void' | 'enter-start' | 'enter' = 'void';
98+
_panelAnimationState: 'void' | 'enter' = 'void';
9999

100100
/** Parent menu of the current menu panel. */
101101
parentMenu: MatMenuPanel | undefined;
@@ -191,6 +191,10 @@ export class MatMenu implements AfterContentInit, MatMenuPanel, OnDestroy {
191191
private _ngZone: NgZone,
192192
@Inject(MAT_MENU_DEFAULT_OPTIONS) private _defaultOptions: MatMenuDefaultOptions) { }
193193

194+
ngOnInit() {
195+
this.setPositionClasses();
196+
}
197+
194198
ngAfterContentInit() {
195199
this._keyManager = new FocusKeyManager<MatMenuItem>(this.items).withWrap().withTypeAhead();
196200
this._tabSubscription = this._keyManager.tabOut.subscribe(() => this.close.emit('keydown'));
@@ -292,19 +296,18 @@ export class MatMenu implements AfterContentInit, MatMenuPanel, OnDestroy {
292296

293297
/** Starts the enter animation. */
294298
_startAnimation() {
295-
this._panelAnimationState = 'enter-start';
299+
// @deletion-target 6.0.0 Combine with _resetAnimation.
300+
this._panelAnimationState = 'enter';
296301
}
297302

298303
/** Resets the panel animation to its initial state. */
299304
_resetAnimation() {
305+
// @deletion-target 6.0.0 Combine with _startAnimation.
300306
this._panelAnimationState = 'void';
301307
}
302308

303309
/** Callback that is invoked when the panel animation completes. */
304-
_onAnimationDone(event: AnimationEvent) {
305-
// After the initial expansion is done, trigger the second phase of the enter animation.
306-
if (event.toState === 'enter-start') {
307-
this._panelAnimationState = 'enter';
308-
}
310+
_onAnimationDone(_event: AnimationEvent) {
311+
// @deletion-target 6.0.0 Not being used anymore. To be removed.
309312
}
310313
}

src/lib/menu/menu.html

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,9 @@
55
(keydown)="_handleKeydown($event)"
66
(click)="closed.emit('click')"
77
[@transformMenu]="_panelAnimationState"
8-
(@transformMenu.done)="_onAnimationDone($event)"
98
tabindex="-1"
109
role="menu">
11-
<div class="mat-menu-content" [@fadeInItems]="'showing'">
10+
<div class="mat-menu-content">
1211
<ng-content></ng-content>
1312
</div>
1413
</div>

src/lib/menu/menu.scss

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,6 @@ $mat-menu-submenu-indicator-size: 10px !default;
1616
border-radius: $mat-menu-border-radius;
1717
outline: 0;
1818

19-
// Prevent the user from interacting while the panel is still animating.
20-
// This avoids issues where the user could accidentally open a sub-menu,
21-
// because of the `overlapTrigger` option.
22-
&.ng-animating {
23-
pointer-events: none;
24-
}
25-
2619
@include cdk-high-contrast {
2720
outline: solid 1px;
2821
}
@@ -70,6 +63,13 @@ $mat-menu-submenu-indicator-size: 10px !default;
7063
transform: rotateY(180deg) translateY(-50%);
7164
}
7265
}
66+
67+
// Prevent the user from interacting while the panel is still animating.
68+
// This avoids issues where the user could accidentally open a sub-menu,
69+
// because of the `overlapTrigger` option.
70+
.mat-menu-panel.ng-animating & {
71+
pointer-events: none;
72+
}
7373
}
7474

7575
button.mat-menu-item {

src/lib/select/select-animations.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ import {
1313
style,
1414
transition,
1515
trigger,
16+
query,
17+
animateChild,
18+
group,
1619
} from '@angular/animations';
1720

1821
/**
@@ -45,14 +48,15 @@ export const matSelectAnimations: {
4548
minWidth: 'calc(100% + 64px)', // 64px = 48px padding on the left + 16px padding on the right
4649
transform: 'scaleY(1)'
4750
})),
48-
transition('void => *', [
51+
transition('void => *', group([
52+
query('@fadeInContent', animateChild()),
4953
style({
5054
opacity: 0,
5155
minWidth: '100%',
5256
transform: 'scaleY(0)'
5357
}),
5458
animate('150ms cubic-bezier(0.25, 0.8, 0.25, 1)')
55-
]),
59+
])),
5660
transition('* => void', [
5761
animate('250ms 100ms linear', style({opacity: 0}))
5862
])

0 commit comments

Comments
 (0)