Skip to content

refactor: export component animations for reuse #8971

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jan 4, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions src/lib/dialog/dialog-animations.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {
animate,
state,
style,
transition,
trigger,
AnimationTriggerMetadata,
} from '@angular/animations';

/** Animations used by MatDialog. */
export const matDialogAnimations: {
readonly slideDialog: AnimationTriggerMetadata;
} = {
/** Animation that slides the dialog in and out of view and fades the opacity. */
slideDialog: trigger('slideDialog', [
// Note: The `enter` animation doesn't transition to something like `translate3d(0, 0, 0)
// scale(1)`, because for some reason specifying the transform explicitly, causes IE both
// to blur the dialog content and decimate the animation performance. Leaving it as `none`
// solves both issues.
state('enter', style({ transform: 'none', opacity: 1 })),
state('void', style({ transform: 'translate3d(0, 25%, 0) scale(0.9)', opacity: 0 })),
state('exit', style({ transform: 'translate3d(0, 25%, 0)', opacity: 0 })),
transition('* => *', animate('400ms cubic-bezier(0.25, 0.8, 0.25, 1)')),
])
};
16 changes: 3 additions & 13 deletions src/lib/dialog/dialog-container.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,9 @@ import {
ViewEncapsulation,
ChangeDetectionStrategy,
} from '@angular/core';
import {animate, AnimationEvent, state, style, transition, trigger} from '@angular/animations';
import {DOCUMENT} from '@angular/common';
import {AnimationEvent} from '@angular/animations';
import {matDialogAnimations} from './dialog-animations';
import {
BasePortalOutlet,
ComponentPortal,
Expand Down Expand Up @@ -55,18 +56,7 @@ export function throwMatDialogContentAlreadyAttachedError() {
// Using OnPush for dialogs caused some G3 sync issues. Disabled until we can track them down.
// tslint:disable-next-line:validate-decorators
changeDetection: ChangeDetectionStrategy.Default,
animations: [
trigger('slideDialog', [
// Note: The `enter` animation doesn't transition to something like `translate3d(0, 0, 0)
// scale(1)`, because for some reason specifying the transform explicitly, causes IE both
// to blur the dialog content and decimate the animation performance. Leaving it as `none`
// solves both issues.
state('enter', style({ transform: 'none', opacity: 1 })),
state('void', style({ transform: 'translate3d(0, 25%, 0) scale(0.9)', opacity: 0 })),
state('exit', style({ transform: 'translate3d(0, 25%, 0)', opacity: 0 })),
transition('* => *', animate('400ms cubic-bezier(0.25, 0.8, 0.25, 1)')),
])
],
animations: [matDialogAnimations.slideDialog],
host: {
'class': 'mat-dialog-container',
'tabindex': '-1',
Expand Down
2 changes: 1 addition & 1 deletion src/lib/dialog/public-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,4 @@ export * from './dialog-container';
export * from './dialog-content-directives';
export * from './dialog-config';
export * from './dialog-ref';

export * from './dialog-animations';
54 changes: 54 additions & 0 deletions src/lib/expansion/expansion-animations.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {
animate,
state,
style,
transition,
trigger,
AnimationTriggerMetadata,
} from '@angular/animations';

/** Time and timing curve for expansion panel animations. */
export const EXPANSION_PANEL_ANIMATION_TIMING = '225ms cubic-bezier(0.4,0.0,0.2,1)';

/** Animations used by the Material expansion panel. */
export const matExpansionAnimations: {
readonly indicatorRotate: AnimationTriggerMetadata;
readonly expansionHeaderHeight: AnimationTriggerMetadata;
readonly bodyExpansion: AnimationTriggerMetadata;
} = {
/** Animation that rotates the indicator arrow. */
indicatorRotate: trigger('indicatorRotate', [
state('collapsed', style({transform: 'rotate(0deg)'})),
state('expanded', style({transform: 'rotate(180deg)'})),
transition('expanded <=> collapsed', animate(EXPANSION_PANEL_ANIMATION_TIMING)),
]),

/** Animation that expands and collapses the panel header height. */
expansionHeaderHeight: trigger('expansionHeight', [
state('collapsed', style({
height: '{{collapsedHeight}}',
}), {
params: {collapsedHeight: '48px'},
}),
state('expanded', style({
height: '{{expandedHeight}}'
}), {
params: {expandedHeight: '64px'}
}),
transition('expanded <=> collapsed', animate(EXPANSION_PANEL_ANIMATION_TIMING)),
]),

/** Animation that expands and collapses the panel content. */
bodyExpansion: trigger('bodyExpansion', [
state('collapsed', style({height: '0px', visibility: 'hidden'})),
state('expanded', style({height: '*', visibility: 'visible'})),
transition('expanded <=> collapsed', animate(EXPANSION_PANEL_ANIMATION_TIMING)),
])
};
28 changes: 6 additions & 22 deletions src/lib/expansion/expansion-panel-header.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 {animate, state, style, transition, trigger} from '@angular/animations';
import {FocusMonitor} from '@angular/cdk/a11y';
import {ENTER, SPACE} from '@angular/cdk/keycodes';
import {filter} from 'rxjs/operators/filter';
Expand All @@ -23,7 +22,8 @@ import {
} from '@angular/core';
import {merge} from 'rxjs/observable/merge';
import {Subscription} from 'rxjs/Subscription';
import {EXPANSION_PANEL_ANIMATION_TIMING, MatExpansionPanel} from './expansion-panel';
import {MatExpansionPanel} from './expansion-panel';
import {matExpansionAnimations} from './expansion-animations';


/**
Expand All @@ -41,6 +41,10 @@ import {EXPANSION_PANEL_ANIMATION_TIMING, MatExpansionPanel} from './expansion-p
encapsulation: ViewEncapsulation.None,
preserveWhitespaces: false,
changeDetection: ChangeDetectionStrategy.OnPush,
animations: [
matExpansionAnimations.indicatorRotate,
matExpansionAnimations.expansionHeaderHeight
],
host: {
'class': 'mat-expansion-panel-header',
'role': 'button',
Expand All @@ -59,26 +63,6 @@ import {EXPANSION_PANEL_ANIMATION_TIMING, MatExpansionPanel} from './expansion-p
}
}`,
},
animations: [
trigger('indicatorRotate', [
state('collapsed', style({transform: 'rotate(0deg)'})),
state('expanded', style({transform: 'rotate(180deg)'})),
transition('expanded <=> collapsed', animate(EXPANSION_PANEL_ANIMATION_TIMING)),
]),
trigger('expansionHeight', [
state('collapsed', style({
height: '{{collapsedHeight}}',
}), {
params: {collapsedHeight: '48px'},
}),
state('expanded', style({
height: '{{expandedHeight}}'
}), {
params: {expandedHeight: '64px'}
}),
transition('expanded <=> collapsed', animate(EXPANSION_PANEL_ANIMATION_TIMING)),
]),
],
})
export class MatExpansionPanelHeader implements OnDestroy {
private _parentChangeSubscription = Subscription.EMPTY;
Expand Down
13 changes: 2 additions & 11 deletions src/lib/expansion/expansion-panel.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 {animate, state, style, transition, trigger} from '@angular/animations';
import {
ChangeDetectionStrategy,
ChangeDetectorRef,
Expand Down Expand Up @@ -35,9 +34,7 @@ import {startWith} from 'rxjs/operators/startWith';
import {MatAccordion} from './accordion';
import {coerceBooleanProperty} from '@angular/cdk/coercion';
import {MatExpansionPanelContent} from './expansion-panel-content';

/** Time and timing curve for expansion panel animations. */
export const EXPANSION_PANEL_ANIMATION_TIMING = '225ms cubic-bezier(0.4,0.0,0.2,1)';
import {matExpansionAnimations} from './expansion-animations';

// Boilerplate for applying mixins to MatExpansionPanel.
/** @docs-private */
Expand Down Expand Up @@ -79,6 +76,7 @@ export type MatExpansionPanelState = 'expanded' | 'collapsed';
changeDetection: ChangeDetectionStrategy.OnPush,
inputs: ['disabled', 'expanded'],
outputs: ['opened', 'closed'],
animations: [matExpansionAnimations.bodyExpansion],
host: {
'class': 'mat-expansion-panel',
'[class.mat-expanded]': 'expanded',
Expand All @@ -87,13 +85,6 @@ export type MatExpansionPanelState = 'expanded' | 'collapsed';
providers: [
{provide: _MatExpansionPanelMixinBase, useExisting: forwardRef(() => MatExpansionPanel)}
],
animations: [
trigger('bodyExpansion', [
state('collapsed', style({height: '0px', visibility: 'hidden'})),
state('expanded', style({height: '*', visibility: 'visible'})),
transition('expanded <=> collapsed', animate(EXPANSION_PANEL_ANIMATION_TIMING)),
]),
],
})
export class MatExpansionPanel extends _MatExpansionPanelMixinBase
implements CanDisable, AfterContentInit, OnChanges, OnDestroy {
Expand Down
1 change: 1 addition & 0 deletions src/lib/expansion/public-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ export * from './accordion';
export * from './expansion-panel';
export * from './expansion-panel-header';
export * from './expansion-panel-content';
export * from './expansion-animations';
30 changes: 30 additions & 0 deletions src/lib/form-field/form-field-animations.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {
animate,
state,
style,
transition,
trigger,
AnimationTriggerMetadata,
} from '@angular/animations';

/** Animations used by the MatFormField. */
export const matFormFieldAnimations: {
readonly transitionMessages: AnimationTriggerMetadata
} = {
/** Animation that transitions the form field's error and hint messages. */
transitionMessages: trigger('transitionMessages', [
// TODO(mmalerba): Use angular animations for label animation as well.
state('enter', style({ opacity: 1, transform: 'translateY(0%)' })),
transition('void => enter', [
style({ opacity: 0, transform: 'translateY(-100%)' }),
animate('300ms cubic-bezier(0.55, 0, 0.55, 0.2)'),
]),
])
};
13 changes: 2 additions & 11 deletions src/lib/form-field/form-field.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 {animate, state, style, transition, trigger} from '@angular/animations';
import {coerceBooleanProperty} from '@angular/cdk/coercion';
import {take} from 'rxjs/operators/take';
import {startWith} from 'rxjs/operators/startWith';
Expand Down Expand Up @@ -41,6 +40,7 @@ import {MatPlaceholder} from './placeholder';
import {MatLabel} from './label';
import {MatPrefix} from './prefix';
import {MatSuffix} from './suffix';
import {matFormFieldAnimations} from './form-field-animations';


let nextUniqueId = 0;
Expand All @@ -57,16 +57,7 @@ let nextUniqueId = 0;
// The MatInput styles are fairly minimal so it shouldn't be a big deal for people who
// aren't using MatInput.
styleUrls: ['form-field.css', '../input/input.css'],
animations: [
// TODO(mmalerba): Use angular animations for label animation as well.
trigger('transitionMessages', [
state('enter', style({ opacity: 1, transform: 'translateY(0%)' })),
transition('void => enter', [
style({ opacity: 0, transform: 'translateY(-100%)' }),
animate('300ms cubic-bezier(0.55, 0, 0.55, 0.2)'),
]),
]),
],
animations: [matFormFieldAnimations.transitionMessages],
host: {
'class': 'mat-input-container mat-form-field',
'[class.mat-input-invalid]': '_control.errorState',
Expand Down
1 change: 1 addition & 0 deletions src/lib/form-field/public-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,4 @@ export * from './placeholder';
export * from './prefix';
export * from './suffix';
export * from './label';
export * from './form-field-animations';
88 changes: 48 additions & 40 deletions src/lib/menu/menu-animations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,50 +16,58 @@ import{
} from '@angular/animations';

/**
* Below are all the animations for the mat-menu component.
* Animations used by the mat-menu component.
* Animation duration and timing values are based on:
* https://material.io/guidelines/components/menus.html#menus-usage
*/
export const matMenuAnimations: {
readonly transformMenu: AnimationTriggerMetadata;
readonly fadeInItems: AnimationTriggerMetadata;
} = {
/**
* This animation controls the menu panel's entry and exit from the page.
*
* When the menu panel is added to the DOM, it scales in and fades in its border.
*
* When the menu panel is removed from the DOM, it simply fades out after a brief
* 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', animate('150ms 50ms linear', style({opacity: 0})))
]),


/**
* This animation controls the menu panel's entry and exit from the page.
*
* When the menu panel is added to the DOM, it scales in and fades in its border.
*
* When the menu panel is removed from the DOM, it simply fades out after a brief
* delay to display the ripple.
*/

// TODO(kara): switch to :enter and :leave once Mobile Safari is sorted out.
export const transformMenu: AnimationTriggerMetadata = trigger('transformMenu', [
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', animate('150ms 50ms linear', style({opacity: 0})))
]);
/**
* This animation fades in the background color and content of the menu panel
* after its containing element is scaled in.
*/
fadeInItems: trigger('fadeInItems', [
state('showing', style({opacity: 1})),
transition('void => *', [
style({opacity: 0}),
animate('400ms 100ms cubic-bezier(0.55, 0, 0.55, 0.2)')
])
])
};

/** @deprecated */
export const fadeInItems = matMenuAnimations.fadeInItems;

/**
* This animation fades in the background color and content of the menu panel
* after its containing element is scaled in.
*/
export const fadeInItems: AnimationTriggerMetadata = trigger('fadeInItems', [
state('showing', style({opacity: 1})),
transition('void => *', [
style({opacity: 0}),
animate('400ms 100ms cubic-bezier(0.55, 0, 0.55, 0.2)')
])
]);
/** @deprecated */
export const transformMenu = matMenuAnimations.transformMenu;
Loading