Skip to content

Commit

Permalink
fix(expansion-panel,menu,select): nested animations not working (#9134)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
crisbeto authored and tinayuangao committed Feb 20, 2018
1 parent 3b5a441 commit 342e3c6
Show file tree
Hide file tree
Showing 6 changed files with 48 additions and 31 deletions.
8 changes: 7 additions & 1 deletion src/lib/expansion/expansion-animations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,13 @@
*/
import {
animate,
animateChild,
group,
state,
style,
transition,
trigger,
query,
AnimationTriggerMetadata,
} from '@angular/animations';

Expand Down Expand Up @@ -42,7 +45,10 @@ export const matExpansionAnimations: {
}), {
params: {expandedHeight: '64px'}
}),
transition('expanded <=> collapsed', animate(EXPANSION_PANEL_ANIMATION_TIMING)),
transition('expanded <=> collapsed', group([
query('@indicatorRotate', animateChild(), {optional: true}),
animate(EXPANSION_PANEL_ANIMATION_TIMING),
])),
]),

/** Animation that expands and collapses the panel content. */
Expand Down
25 changes: 15 additions & 10 deletions src/lib/menu/menu-animations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ import{
style,
animate,
transition,
query,
group,
sequence,
AnimationTriggerMetadata,
} from '@angular/animations';

Expand All @@ -33,22 +36,22 @@ export const matMenuAnimations: {
* delay to display the ripple.
*/
transformMenu: trigger('transformMenu', [
// TODO(kara): switch to :enter and :leave once Mobile Safari is sorted out.
state('void', style({
opacity: 0,
// This starts off from 0.01, instead of 0, because there's an issue in the Angular animations
// as of 4.2, which causes the animation to be skipped if it starts from 0.
transform: 'scale(0.01, 0.01)'
})),
state('enter-start', style({
opacity: 1,
transform: 'scale(1, 0.5)'
})),
state('enter', style({
transform: 'scale(1, 1)'
})),
transition('void => enter-start', animate('100ms linear')),
transition('enter-start => enter', animate('300ms cubic-bezier(0.25, 0.8, 0.25, 1)')),
transition('void => enter', sequence([
query('.mat-menu-content', style({opacity: 0})),
animate('100ms linear', style({opacity: 1, transform: 'scale(1, 0.5)'})),
group([
query('.mat-menu-content', animate('400ms cubic-bezier(0.55, 0, 0.55, 0.2)',
style({opacity: 1})
)),
animate('300ms cubic-bezier(0.25, 0.8, 0.25, 1)', style({transform: 'scale(1, 1)'})),
])
])),
transition('* => void', animate('150ms 50ms linear', style({opacity: 0})))
]),

Expand All @@ -58,6 +61,8 @@ export const matMenuAnimations: {
* after its containing element is scaled in.
*/
fadeInItems: trigger('fadeInItems', [
// TODO(crisbeto): this is inside the `transformMenu`
// now. Remove next time we do breaking changes.
state('showing', style({opacity: 1})),
transition('void => *', [
style({opacity: 0}),
Expand Down
21 changes: 12 additions & 9 deletions src/lib/menu/menu-directive.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
* found in the LICENSE file at https://angular.io/license
*/

import {AnimationEvent} from '@angular/animations';
import {FocusKeyManager} from '@angular/cdk/a11y';
import {Direction} from '@angular/cdk/bidi';
import {ESCAPE, LEFT_ARROW, RIGHT_ARROW} from '@angular/cdk/keycodes';
Expand All @@ -31,6 +30,7 @@ import {
ViewChild,
ViewEncapsulation,
NgZone,
OnInit,
} from '@angular/core';
import {Observable} from 'rxjs/Observable';
import {merge} from 'rxjs/observable/merge';
Expand Down Expand Up @@ -82,7 +82,7 @@ const MAT_MENU_BASE_ELEVATION = 2;
],
exportAs: 'matMenu'
})
export class MatMenu implements AfterContentInit, MatMenuPanel, OnDestroy {
export class MatMenu implements OnInit, AfterContentInit, MatMenuPanel, OnDestroy {
private _keyManager: FocusKeyManager<MatMenuItem>;
private _xPosition: MenuPositionX = this._defaultOptions.xPosition;
private _yPosition: MenuPositionY = this._defaultOptions.yPosition;
Expand All @@ -95,7 +95,7 @@ export class MatMenu implements AfterContentInit, MatMenuPanel, OnDestroy {
_classList: {[key: string]: boolean} = {};

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

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

ngOnInit() {
this.setPositionClasses();
}

ngAfterContentInit() {
this._keyManager = new FocusKeyManager<MatMenuItem>(this.items).withWrap().withTypeAhead();
this._tabSubscription = this._keyManager.tabOut.subscribe(() => this.close.emit('keydown'));
Expand Down Expand Up @@ -292,19 +296,18 @@ export class MatMenu implements AfterContentInit, MatMenuPanel, OnDestroy {

/** Starts the enter animation. */
_startAnimation() {
this._panelAnimationState = 'enter-start';
// @deletion-target 6.0.0 Combine with _resetAnimation.
this._panelAnimationState = 'enter';
}

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

/** Callback that is invoked when the panel animation completes. */
_onAnimationDone(event: AnimationEvent) {
// After the initial expansion is done, trigger the second phase of the enter animation.
if (event.toState === 'enter-start') {
this._panelAnimationState = 'enter';
}
_onAnimationDone(_event: AnimationEvent) {
// @deletion-target 6.0.0 Not being used anymore. To be removed.
}
}
3 changes: 1 addition & 2 deletions src/lib/menu/menu.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,9 @@
(keydown)="_handleKeydown($event)"
(click)="closed.emit('click')"
[@transformMenu]="_panelAnimationState"
(@transformMenu.done)="_onAnimationDone($event)"
tabindex="-1"
role="menu">
<div class="mat-menu-content" [@fadeInItems]="'showing'">
<div class="mat-menu-content">
<ng-content></ng-content>
</div>
</div>
Expand Down
14 changes: 7 additions & 7 deletions src/lib/menu/menu.scss
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,6 @@ $mat-menu-submenu-indicator-size: 10px !default;
border-radius: $mat-menu-border-radius;
outline: 0;

// Prevent the user from interacting while the panel is still animating.
// This avoids issues where the user could accidentally open a sub-menu,
// because of the `overlapTrigger` option.
&.ng-animating {
pointer-events: none;
}

@include cdk-high-contrast {
outline: solid 1px;
}
Expand Down Expand Up @@ -70,6 +63,13 @@ $mat-menu-submenu-indicator-size: 10px !default;
transform: rotateY(180deg) translateY(-50%);
}
}

// Prevent the user from interacting while the panel is still animating.
// This avoids issues where the user could accidentally open a sub-menu,
// because of the `overlapTrigger` option.
.mat-menu-panel.ng-animating & {
pointer-events: none;
}
}

button.mat-menu-item {
Expand Down
8 changes: 6 additions & 2 deletions src/lib/select/select-animations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ import {
style,
transition,
trigger,
query,
animateChild,
group,
} from '@angular/animations';

/**
Expand Down Expand Up @@ -45,14 +48,15 @@ export const matSelectAnimations: {
minWidth: 'calc(100% + 64px)', // 64px = 48px padding on the left + 16px padding on the right
transform: 'scaleY(1)'
})),
transition('void => *', [
transition('void => *', group([
query('@fadeInContent', animateChild()),
style({
opacity: 0,
minWidth: '100%',
transform: 'scaleY(0)'
}),
animate('150ms cubic-bezier(0.25, 0.8, 0.25, 1)')
]),
])),
transition('* => void', [
animate('250ms 100ms linear', style({opacity: 0}))
])
Expand Down

0 comments on commit 342e3c6

Please sign in to comment.