+ Neptune is the eighth and farthest known planet from the Sun in the Solar System. In the
+ Solar System, it is the fourth-largest planet by diameter, the third-most-massive planet,
+ and the densest giant planet. Neptune is 17 times the mass of Earth and is slightly more
+ massive than its near-twin Uranus, which is 15 times the mass of Earth and slightly larger
+ than Neptune. Neptune orbits the Sun once every 164.8 years at an average distance of 30.1
+ astronomical units (4.50×109 km). It is named after the Roman god of the sea and has the
+ astronomical symbol ♆, a stylised version of the god Neptune's trident.
+
+
+
+
+
+
+ Read more on Wikipedia
+
+ `
+})
+export class ContentElementDialog { }
diff --git a/src/lib/dialog/README.md b/src/lib/dialog/README.md
index d68f89f54aff..194b8fe0b969 100644
--- a/src/lib/dialog/README.md
+++ b/src/lib/dialog/README.md
@@ -4,15 +4,16 @@ MdDialog is a service, which opens dialogs components in the view.
### Methods
-| Name | Description |
-| --- | --- |
+| Name | Description |
+| ---- | ----------- |
| `open(component: ComponentType, config: MdDialogConfig): MdDialogRef` | Creates and opens a dialog matching material spec. |
| `closeAll(): void` | Closes all of the dialogs that are currently open. |
+| `closeTop(): void` | Closes the topmost of the open dialogs. |
### Config
-| Key | Description |
-| --- | --- |
+| Key | Description |
+| --- | ------------ |
| `role: DialogRole = 'dialog'` | The ARIA role of the dialog element. Possible values are `dialog` and `alertdialog`. Optional. |
| `disableClose: boolean = false` | Whether to prevent the user from closing a dialog by clicking on the backdrop or pressing escape. Optional. |
| `width: string = ''` | Width of the dialog. Takes any valid CSS value. Optional. |
@@ -26,11 +27,19 @@ A reference to the dialog created by the MdDialog `open` method.
### Methods
-| Name | Description |
-| --- | --- |
+| Name | Description |
+| ---- | ----------- |
| `close(dialogResult?: any)` | Closes the dialog, pushing a value to the afterClosed observable. |
| `afterClosed(): Observable` | Returns an observable which will emit the dialog result, passed to the `close` method above. |
+### Directives
+| Name | Description |
+| --- | ------------ |
+| `md-dialog-title` | Marks the title of the dialog.
+| `md-dialog-content` | Scrollable content of the dialog.
+| `md-dialog-close` | When added to a `button`, makes the element act as a close button for the dialog.
+| `md-dialog-actions` | Wrapper for the set of actions at the bottom of a dialog. Typically contains buttons.
+
## Example
The service can be injected in a component.
@@ -62,8 +71,12 @@ export class PizzaComponent {
@Component({
selector: 'pizza-dialog',
template: `
-
-
+
Would you like to order pizza?
+
+
+
+
+
`
})
export class PizzaDialog {
diff --git a/src/lib/dialog/dialog-container.scss b/src/lib/dialog/dialog-container.scss
deleted file mode 100644
index c7675efbbbcc..000000000000
--- a/src/lib/dialog/dialog-container.scss
+++ /dev/null
@@ -1,24 +0,0 @@
-@import '../core/style/elevation';
-@import '../core/a11y/a11y';
-
-
-$md-dialog-padding: 24px !default;
-$md-dialog-border-radius: 2px !default;
-
-md-dialog-container {
- @include md-elevation(24);
-
- display: block;
- padding: $md-dialog-padding;
- border-radius: $md-dialog-border-radius;
- box-sizing: border-box;
- overflow: auto;
-
- // The dialog container should completely fill its parent overlay element.
- width: 100%;
- height: 100%;
-
- @include md-high-contrast {
- outline: solid 1px;
- }
-}
diff --git a/src/lib/dialog/dialog-container.ts b/src/lib/dialog/dialog-container.ts
index 39a2db89cc50..c9726d9499c3 100644
--- a/src/lib/dialog/dialog-container.ts
+++ b/src/lib/dialog/dialog-container.ts
@@ -22,7 +22,7 @@ import 'rxjs/add/operator/first';
moduleId: module.id,
selector: 'md-dialog-container, mat-dialog-container',
templateUrl: 'dialog-container.html',
- styleUrls: ['dialog-container.css'],
+ styleUrls: ['dialog.css'],
host: {
'class': 'md-dialog-container',
'[attr.role]': 'dialogConfig?.role',
diff --git a/src/lib/dialog/dialog-content-directives.ts b/src/lib/dialog/dialog-content-directives.ts
new file mode 100644
index 000000000000..a7c8e3875ef1
--- /dev/null
+++ b/src/lib/dialog/dialog-content-directives.ts
@@ -0,0 +1,47 @@
+import {Directive, Input} from '@angular/core';
+import {MdDialogRef} from './dialog-ref';
+
+
+/**
+ * Button that will close the current dialog.
+ */
+@Directive({
+ selector: 'button[md-dialog-close], button[mat-dialog-close]',
+ host: {
+ '(click)': 'dialogRef.close()',
+ '[attr.aria-label]': 'ariaLabel'
+ }
+})
+export class MdDialogClose {
+ /** Screenreader label for the button. */
+ @Input('aria-label') ariaLabel: string = 'Close dialog';
+
+ constructor(public dialogRef: MdDialogRef) { }
+}
+
+/**
+ * Title of a dialog element. Stays fixed to the top of the dialog when scrolling.
+ */
+@Directive({
+ selector: '[md-dialog-title], [mat-dialog-title]'
+})
+export class MdDialogTitle { }
+
+
+/**
+ * Scrollable content container of a dialog.
+ */
+@Directive({
+ selector: '[md-dialog-content], md-dialog-content, [mat-dialog-content], mat-dialog-content'
+})
+export class MdDialogContent { }
+
+
+/**
+ * Container for the bottom action buttons in a dialog.
+ * Stays fixed to the bottom when scrolling.
+ */
+@Directive({
+ selector: '[md-dialog-actions], md-dialog-actions, [mat-dialog-actions], mat-dialog-actions'
+})
+export class MdDialogActions { }
diff --git a/src/lib/dialog/dialog.scss b/src/lib/dialog/dialog.scss
new file mode 100644
index 000000000000..06492d08629c
--- /dev/null
+++ b/src/lib/dialog/dialog.scss
@@ -0,0 +1,54 @@
+@import '../core/style/elevation';
+@import '../core/a11y/a11y';
+
+
+$md-dialog-padding: 24px !default;
+$md-dialog-border-radius: 2px !default;
+$md-dialog-max-width: 80vw !default;
+$md-dialog-max-height: 65vh !default;
+
+md-dialog-container {
+ @include md-elevation(24);
+
+ display: block;
+ padding: $md-dialog-padding;
+ border-radius: $md-dialog-border-radius;
+ box-sizing: border-box;
+ overflow: auto;
+ max-width: $md-dialog-max-width;
+
+ // The dialog container should completely fill its parent overlay element.
+ width: 100%;
+ height: 100%;
+
+ @include md-high-contrast {
+ outline: solid 1px;
+ }
+}
+
+md-dialog-content, [md-dialog-content], mat-dialog-content, [mat-dialog-content] {
+ display: block;
+ margin: 0 $md-dialog-padding * -1;
+ padding: 0 $md-dialog-padding;
+ max-height: $md-dialog-max-height;
+ overflow: auto;
+}
+
+[md-dialog-title], [mat-dialog-title] {
+ font-size: 20px;
+ font-weight: bold;
+ margin: 0 0 20px;
+ display: block;
+}
+
+md-dialog-actions, [md-dialog-actions], mat-dialog-actions, [mat-dialog-actions] {
+ padding: $md-dialog-padding / 2 0;
+ display: block;
+
+ &:last-child {
+ // If the actions are the last element in a dialog, we need to pull them down
+ // over the dialog padding, in order to avoid the action's padding stacking
+ // with the dialog's.
+ margin-bottom: -$md-dialog-padding;
+ }
+}
diff --git a/src/lib/dialog/dialog.spec.ts b/src/lib/dialog/dialog.spec.ts
index 34855db3f59a..e88377b7593d 100644
--- a/src/lib/dialog/dialog.spec.ts
+++ b/src/lib/dialog/dialog.spec.ts
@@ -9,7 +9,8 @@ import {
} from '@angular/core/testing';
import {By} from '@angular/platform-browser';
import {NgModule, Component, Directive, ViewChild, ViewContainerRef} from '@angular/core';
-import {MdDialog, MdDialogModule} from './dialog';
+import {MdDialogModule} from './index';
+import {MdDialog} from './dialog';
import {OverlayContainer} from '../core';
import {MdDialogRef} from './dialog-ref';
import {MdDialogContainer} from './dialog-container';
@@ -308,6 +309,41 @@ describe('MdDialog', () => {
.toBe('dialog-trigger', 'Expected that the trigger was refocused after dialog close');
}));
});
+
+ describe('dialog content elements', () => {
+ let dialogRef: MdDialogRef;
+
+ beforeEach(() => {
+ dialogRef = dialog.open(ContentElementDialog);
+ viewContainerFixture.detectChanges();
+ });
+
+ it('should close the dialog when clicking on the close button', () => {
+ expect(overlayContainerElement.querySelectorAll('.md-dialog-container').length).toBe(1);
+
+ (overlayContainerElement.querySelector('button[md-dialog-close]') as HTMLElement).click();
+
+ expect(overlayContainerElement.querySelectorAll('.md-dialog-container').length).toBe(0);
+ });
+
+ it('should not close the dialog if [md-dialog-close] is applied on a non-button node', () => {
+ expect(overlayContainerElement.querySelectorAll('.md-dialog-container').length).toBe(1);
+
+ (overlayContainerElement.querySelector('div[md-dialog-close]') as HTMLElement).click();
+
+ expect(overlayContainerElement.querySelectorAll('.md-dialog-container').length).toBe(1);
+ });
+
+ it('should allow for a user-specified aria-label on the close button', () => {
+ let button = overlayContainerElement.querySelector('button[md-dialog-close]');
+
+ dialogRef.componentInstance.closeButtonAriaLabel = 'Best close button ever';
+ viewContainerFixture.detectChanges();
+
+ expect(button.getAttribute('aria-label')).toBe('Best close button ever');
+ });
+
+ });
});
@@ -334,13 +370,33 @@ class PizzaMsg {
constructor(public dialogRef: MdDialogRef) { }
}
+@Component({
+ template: `
+