4 Use `Polymer.PaperDialogBehavior` and `paper-dialog-common.css` to implement a Material Design
7 For example, if `<paper-dialog-impl>` implements this behavior:
11 <div>Dialog body</div>
13 <paper-button dialog-dismiss>Cancel</paper-button>
14 <paper-button dialog-confirm>Accept</paper-button>
18 `paper-dialog-common.css` provide styles for a header, content area, and an action area for buttons.
19 Use the `<h2>` tag for the header and the `buttons` class for the action area. You can use the
20 `paper-dialog-scrollable` element (in its own repository) if you need a scrolling content area.
22 Use the `dialog-dismiss` and `dialog-confirm` attributes on interactive controls to close the
23 dialog. If the user dismisses the dialog with `dialog-confirm`, the `closingReason` will update
24 to include `confirmed: true`.
28 The following custom properties and mixins are available for styling.
30 Custom property | Description | Default
31 ----------------|-------------|----------
32 `--paper-dialog-background-color` | Dialog background color | `--primary-background-color`
33 `--paper-dialog-color` | Dialog foreground color | `--primary-text-color`
34 `--paper-dialog` | Mixin applied to the dialog | `{}`
35 `--paper-dialog-title` | Mixin applied to the title (`<h2>`) element | `{}`
36 `--paper-dialog-button-color` | Button area foreground color | `--default-primary-color`
40 This element has `role="dialog"` by default. Depending on the context, it may be more appropriate
41 to override this attribute with `role="alertdialog"`.
43 If `modal` is set, the element will set `aria-modal` and prevent the focus from exiting the element.
44 It will also ensure that focus remains in the dialog.
46 The `aria-labelledby` attribute will be set to the header element, if one exists.
50 @polymerBehavior Polymer.PaperDialogBehavior
53 Polymer
.PaperDialogBehaviorImpl
= {
63 * If `modal` is true, this implies `no-cancel-on-outside-click` and `with-backdrop`.
66 observer
: '_modalChanged',
72 _lastFocusedElement
: {
79 return this._onFocus
.bind(this);
83 _boundOnBackdropClick
: {
86 return this._onBackdropClick
.bind(this);
93 'click': '_onDialogClick',
94 'iron-overlay-opened': '_onIronOverlayOpened',
95 'iron-overlay-closed': '_onIronOverlayClosed'
98 attached: function() {
99 this._observer
= this._observe(this);
100 this._updateAriaLabelledBy();
103 detached: function() {
104 if (this._observer
) {
105 this._observer
.disconnect();
109 _observe: function(node
) {
110 var observer
= new MutationObserver(function() {
111 this._updateAriaLabelledBy();
113 observer
.observe(node
, {
120 _modalChanged: function() {
122 this.setAttribute('aria-modal', 'true');
124 this.setAttribute('aria-modal', 'false');
126 // modal implies noCancelOnOutsideClick and withBackdrop if true, don't overwrite
127 // those properties otherwise.
129 this.noCancelOnOutsideClick
= true;
130 this.withBackdrop
= true;
134 _updateAriaLabelledBy: function() {
135 var header
= Polymer
.dom(this).querySelector('h2');
137 this.removeAttribute('aria-labelledby');
140 var headerId
= header
.getAttribute('id');
141 if (headerId
&& this.getAttribute('aria-labelledby') === headerId
) {
144 // set aria-describedBy to the header element
147 labelledById
= headerId
;
149 labelledById
= 'paper-dialog-header-' + new Date().getUTCMilliseconds();
150 header
.setAttribute('id', labelledById
);
152 this.setAttribute('aria-labelledby', labelledById
);
155 _updateClosingReasonConfirmed: function(confirmed
) {
156 this.closingReason
= this.closingReason
|| {};
157 this.closingReason
.confirmed
= confirmed
;
160 _onDialogClick: function(event
) {
161 var target
= event
.target
;
162 while (target
&& target
!== this) {
163 if (target
.hasAttribute
) {
164 if (target
.hasAttribute('dialog-dismiss')) {
165 this._updateClosingReasonConfirmed(false);
168 } else if (target
.hasAttribute('dialog-confirm')) {
169 this._updateClosingReasonConfirmed(true);
174 target
= target
.parentNode
;
178 _onIronOverlayOpened: function() {
180 document
.body
.addEventListener('focus', this._boundOnFocus
, true);
181 this.backdropElement
.addEventListener('click', this._boundOnBackdropClick
);
185 _onIronOverlayClosed: function() {
186 document
.body
.removeEventListener('focus', this._boundOnFocus
, true);
187 this.backdropElement
.removeEventListener('click', this._boundOnBackdropClick
);
190 _onFocus: function(event
) {
192 var target
= event
.target
;
193 while (target
&& target
!== this && target
!== document
.body
) {
194 target
= target
.parentNode
;
197 if (target
=== document
.body
) {
198 if (this._lastFocusedElement
) {
199 this._lastFocusedElement
.focus();
201 this._focusNode
.focus();
204 this._lastFocusedElement
= event
.target
;
210 _onBackdropClick: function() {
212 if (this._lastFocusedElement
) {
213 this._lastFocusedElement
.focus();
215 this._focusNode
.focus();
222 /** @polymerBehavior */
223 Polymer
.PaperDialogBehavior
= [Polymer
.IronOverlayBehavior
, Polymer
.PaperDialogBehaviorImpl
];