Skip to content

Commit 7b8856a

Browse files
committed
feat(material/dialog): add the ability to control the animation duration
Since the dialog animation is on the `MatDialogContainer`, consumers aren't able to disable the animation. These changes add properties to the dialog config that allow consumers to set the duration of the dialog's enter and exit animations. Fixes #3616.
1 parent f69cf6c commit 7b8856a

File tree

13 files changed

+124
-3
lines changed

13 files changed

+124
-3
lines changed
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<h1 mat-dialog-title>Delete file</h1>
2+
<div mat-dialog-content>
3+
Would you like to delete cat.jpeg?
4+
</div>
5+
<div mat-dialog-actions>
6+
<button mat-button mat-dialog-close>No</button>
7+
<button mat-button mat-dialog-close cdkFocusInitial>Ok</button>
8+
</div>
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
button {
2+
margin-right: 8px;
3+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
<button mat-raised-button (click)="openDialog('0ms', '0ms')">Open dialog without animation</button>
2+
<button mat-raised-button (click)="openDialog('3000ms', '1500ms')">Open dialog slowly</button>
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import {Component} from '@angular/core';
2+
import {MatDialog, MatDialogRef} from '@angular/material/dialog';
3+
4+
/**
5+
* @title Dialog Animations
6+
*/
7+
@Component({
8+
selector: 'dialog-animations-example',
9+
styleUrls: ['dialog-animations-example.css'],
10+
templateUrl: 'dialog-animations-example.html',
11+
})
12+
export class DialogAnimationsExample {
13+
constructor(public dialog: MatDialog) {}
14+
15+
openDialog(enterAnimationDuration: string, exitAnimationDuration: string): void {
16+
this.dialog.open(DialogAnimationsExampleDialog, {
17+
width: '250px',
18+
enterAnimationDuration,
19+
exitAnimationDuration
20+
});
21+
}
22+
}
23+
24+
@Component({
25+
selector: 'dialog-animations-example-dialog',
26+
templateUrl: 'dialog-animations-example-dialog.html',
27+
})
28+
export class DialogAnimationsExampleDialog {
29+
constructor(public dialogRef: MatDialogRef<DialogAnimationsExampleDialog>) {}
30+
}

src/components-examples/material/dialog/index.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@ import {
2323
DialogFromMenuExampleDialog,
2424
} from './dialog-from-menu/dialog-from-menu-example';
2525
import {DialogHarnessExample} from './dialog-harness/dialog-harness-example';
26+
import {
27+
DialogAnimationsExample,
28+
DialogAnimationsExampleDialog,
29+
} from './dialog-animations/dialog-animations-example';
2630

2731
export {
2832
DialogContentExample,
@@ -36,6 +40,8 @@ export {
3640
DialogHarnessExample,
3741
DialogOverviewExample,
3842
DialogOverviewExampleDialog,
43+
DialogAnimationsExample,
44+
DialogAnimationsExampleDialog,
3945
};
4046

4147
const EXAMPLES = [
@@ -50,6 +56,8 @@ const EXAMPLES = [
5056
DialogHarnessExample,
5157
DialogOverviewExample,
5258
DialogOverviewExampleDialog,
59+
DialogAnimationsExample,
60+
DialogAnimationsExampleDialog,
5361
];
5462

5563
@NgModule({

src/dev-app/dialog/dialog-demo.html

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,17 @@ <h2>Other options</h2>
102102
</mat-form-field>
103103
</p>
104104

105+
<p>
106+
<mat-form-field>
107+
<mat-label>Enter duration</mat-label>
108+
<input matInput [(ngModel)]="config.enterAnimationDuration">
109+
</mat-form-field>
110+
<mat-form-field>
111+
<mat-label>Exit duration</mat-label>
112+
<input matInput [(ngModel)]="config.exitAnimationDuration">
113+
</mat-form-field>
114+
</p>
115+
105116
<p>
106117
<mat-checkbox [(ngModel)]="config.disableClose">Disable close</mat-checkbox>
107118
</p>

src/dev-app/dialog/dialog-demo.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ export class DialogDemo {
3131
height: '',
3232
minWidth: '',
3333
minHeight: '',
34+
enterAnimationDuration: defaultDialogConfig.enterAnimationDuration,
35+
exitAnimationDuration: defaultDialogConfig.exitAnimationDuration,
3436
maxWidth: defaultDialogConfig.maxWidth,
3537
maxHeight: '',
3638
position: {

src/material/dialog/dialog-animations.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,14 @@ export const matDialogAnimations: {
3030
state('enter', style({transform: 'none'})),
3131
transition(
3232
'* => enter',
33-
animate('150ms cubic-bezier(0, 0, 0.2, 1)', style({transform: 'none', opacity: 1})),
33+
animate(
34+
'{{enterAnimationDuration}} cubic-bezier(0, 0, 0.2, 1)',
35+
style({transform: 'none', opacity: 1}),
36+
),
3437
),
3538
transition(
3639
'* => void, * => exit',
37-
animate('75ms cubic-bezier(0.4, 0.0, 0.2, 1)', style({opacity: 0})),
40+
animate('{{exitAnimationDuration}} cubic-bezier(0.4, 0.0, 0.2, 1)', style({opacity: 0})),
3841
),
3942
]),
4043
};

src/material/dialog/dialog-config.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,5 +123,11 @@ export class MatDialogConfig<D = any> {
123123
/** Alternate `ComponentFactoryResolver` to use when resolving the associated component. */
124124
componentFactoryResolver?: ComponentFactoryResolver;
125125

126+
/** Duration of the enter animation. Has to be a valid CSS value (e.g. 100ms). */
127+
enterAnimationDuration?: string = '150ms';
128+
129+
/** Duration of the exit animation. Has to be a valid CSS value (e.g. 50ms). */
130+
exitAnimationDuration?: string = '75ms';
131+
126132
// TODO(jelbourn): add configuration for lifecycle hooks, ARIA labelling.
127133
}

src/material/dialog/dialog-container.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -321,7 +321,13 @@ export abstract class _MatDialogContainerBase extends BasePortalOutlet {
321321
'[attr.aria-labelledby]': '_config.ariaLabel ? null : _ariaLabelledBy',
322322
'[attr.aria-label]': '_config.ariaLabel',
323323
'[attr.aria-describedby]': '_config.ariaDescribedBy || null',
324-
'[@dialogContainer]': '_state',
324+
'[@dialogContainer]': `{
325+
value: _state,
326+
params: {
327+
enterAnimationDuration: _config.enterAnimationDuration,
328+
exitAnimationDuration: _config.exitAnimationDuration
329+
}
330+
}`,
325331
'(@dialogContainer.start)': '_onAnimationStart($event)',
326332
'(@dialogContainer.done)': '_onAnimationDone($event)',
327333
},

src/material/dialog/dialog.md

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,44 @@ You can control which elements are tab stops with the `tabindex` attribute
150150

151151
<!-- example(dialog-content) -->
152152

153+
### Configuring dialog content via `entryComponents`
154+
155+
Because `MatDialog` instantiates components at run-time, the Angular compiler needs extra
156+
information to create the necessary `ComponentFactory` for your dialog content component.
157+
158+
For any component loaded into a dialog, you must include your component class in the list of
159+
`entryComponents` in your NgModule definition so that the Angular compiler knows to create
160+
the `ComponentFactory` for it.
161+
162+
```ts
163+
@NgModule({
164+
imports: [
165+
// ...
166+
MatDialogModule
167+
],
168+
169+
declarations: [
170+
AppComponent,
171+
ExampleDialogComponent
172+
],
173+
174+
entryComponents: [
175+
ExampleDialogComponent
176+
],
177+
178+
providers: [],
179+
bootstrap: [AppComponent]
180+
})
181+
export class AppModule {}
182+
```
183+
184+
### Controlling the dialog animation
185+
You can control the duration of the dialog's enter and exit animations using the
186+
`enterAnimationDuration` and `exitAnimationDuration` options. If you want to disable the dialog's
187+
animation completely, you can do so by setting the properties to `0ms`.
188+
189+
<!-- example(dialog-animations) -->
190+
153191
### Accessibility
154192

155193
`MatDialog` creates modal dialogs that implements the ARIA `role="dialog"` pattern by default.

src/material/dialog/dialog.spec.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1938,6 +1938,8 @@ describe('MatDialog with default options', () => {
19381938
minHeight: '50px',
19391939
maxWidth: '150px',
19401940
maxHeight: '150px',
1941+
enterAnimationDuration: '100ms',
1942+
exitAnimationDuration: '50ms',
19411943
autoFocus: false,
19421944
};
19431945

tools/public_api_guard/material/dialog.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,8 @@ export class MatDialogConfig<D = any> {
164164
data?: D | null;
165165
direction?: Direction;
166166
disableClose?: boolean;
167+
enterAnimationDuration?: string;
168+
exitAnimationDuration?: string;
167169
hasBackdrop?: boolean;
168170
height?: string;
169171
id?: string;

0 commit comments

Comments
 (0)