Skip to content

Commit a2700b2

Browse files
committed
fix(expansion-panel,menu,select): nested animations not working
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 15100ed commit a2700b2

File tree

6 files changed

+44
-36
lines changed

6 files changed

+44
-36
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: 13 additions & 19 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';
@@ -30,6 +29,7 @@ import {
3029
ViewChild,
3130
ViewEncapsulation,
3231
NgZone,
32+
OnInit,
3333
} from '@angular/core';
3434
import {Observable} from 'rxjs/Observable';
3535
import {merge} from 'rxjs/observable/merge';
@@ -79,7 +79,7 @@ const MAT_MENU_BASE_ELEVATION = 2;
7979
],
8080
exportAs: 'matMenu'
8181
})
82-
export class MatMenu implements AfterContentInit, MatMenuPanel, OnDestroy {
82+
export class MatMenu implements OnInit, AfterContentInit, MatMenuPanel, OnDestroy {
8383
private _keyManager: FocusKeyManager<MatMenuItem>;
8484
private _xPosition: MenuPositionX = this._defaultOptions.xPosition;
8585
private _yPosition: MenuPositionY = this._defaultOptions.yPosition;
@@ -92,7 +92,7 @@ export class MatMenu implements AfterContentInit, MatMenuPanel, OnDestroy {
9292
_classList: {[key: string]: boolean} = {};
9393

9494
/** Current state of the panel animation. */
95-
_panelAnimationState: 'void' | 'enter-start' | 'enter' = 'void';
95+
_panelAnimationState: 'void' | 'enter' = 'void';
9696

9797
/** Parent menu of the current menu panel. */
9898
parentMenu: MatMenuPanel | undefined;
@@ -181,6 +181,10 @@ export class MatMenu implements AfterContentInit, MatMenuPanel, OnDestroy {
181181
private _ngZone: NgZone,
182182
@Inject(MAT_MENU_DEFAULT_OPTIONS) private _defaultOptions: MatMenuDefaultOptions) { }
183183

184+
ngOnInit() {
185+
this.setPositionClasses();
186+
}
187+
184188
ngAfterContentInit() {
185189
this._keyManager = new FocusKeyManager<MatMenuItem>(this.items).withWrap().withTypeAhead();
186190
this._tabSubscription = this._keyManager.tabOut.subscribe(() => this.close.emit('keydown'));
@@ -273,21 +277,11 @@ export class MatMenu implements AfterContentInit, MatMenuPanel, OnDestroy {
273277
}
274278
}
275279

276-
/** Starts the enter animation. */
277-
_startAnimation() {
278-
this._panelAnimationState = 'enter-start';
279-
}
280-
281-
/** Resets the panel animation to its initial state. */
282-
_resetAnimation() {
283-
this._panelAnimationState = 'void';
284-
}
285-
286-
/** Callback that is invoked when the panel animation completes. */
287-
_onAnimationDone(event: AnimationEvent) {
288-
// After the initial expansion is done, trigger the second phase of the enter animation.
289-
if (event.toState === 'enter-start') {
290-
this._panelAnimationState = 'enter';
291-
}
280+
/**
281+
* Toggles the animation state of the menu panel.
282+
* @param isOpen Whether the menu should be open.
283+
*/
284+
_toggleAnimation(isOpen: boolean) {
285+
this._panelAnimationState = isOpen ? 'enter' : 'void';
292286
}
293287
}

src/lib/menu/menu-trigger.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ export class MatMenuTrigger implements AfterContentInit, OnDestroy {
197197
this._initMenu();
198198

199199
if (this.menu instanceof MatMenu) {
200-
this.menu._startAnimation();
200+
this.menu._toggleAnimation(true);
201201
}
202202
}
203203
}
@@ -220,7 +220,7 @@ export class MatMenuTrigger implements AfterContentInit, OnDestroy {
220220
this._overlayRef.detach();
221221

222222
if (this.menu instanceof MatMenu) {
223-
this.menu._resetAnimation();
223+
this.menu._toggleAnimation(false);
224224
}
225225
}
226226
}

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/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)