Skip to content
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

Edit: <dialog> element #22786

Merged
merged 2 commits into from
Dec 7, 2022
Merged
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
51 changes: 22 additions & 29 deletions files/en-us/web/html/element/dialog/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,30 +81,28 @@ This element includes the [global attributes](/en-US/docs/Web/HTML/Global_attrib

- {{htmlattrdef("open")}}
- : Indicates that the dialog is active and can be interacted with. When the `open` attribute is not set, the dialog _shouldn't_ be shown to the user.
It is recommended to use the `.show()` or `.showModal()` methods to render dialogs, rather than the `open` attribute.
It is recommended to use the `.show()` or `.showModal()` methods to render dialogs, rather than the `open` attribute. If a `<dialog>` is opened using the `open` attribute, it will be non-modal.

## Accessibility considerations

To ensure accessibility for users of Safari versions below 15.4, consider using a polyfill such as [a11y-dialog](https://a11y-dialog.netlify.app/) as earlier implementations of the `<dialog>` element had [usability issues with some forms of assistive technology](https://www.scottohara.me/blog/2019/03/05/open-dialog.html).
The native HTML `<dialog>` element should be used in creating modal dialogs as it provides usability and accessiblity features that must be replicated if using other elements for a similar purpose. Use the appropriate `.showModal()` or `.show()` method to render dialogs. If creating a custom dialog implementation, ensure all expected default behaviors are supported and proper labeling recommendations are followed.

When implementing a dialog, it is important to consider the most appropriate place to set user focus. Explicitly indicating the initial focus placement by use of the [autofocus](/en-US/docs/Web/HTML/Global_attributes/autofocus) attribute will help ensure initial focus is set to the element deemed the best initial focus placement for any particular dialog. When in doubt, as it may not always be known where initial focus could be set within a dialog, particularly for instances where a dialog's content is dynamically rendered when invoked, then if necessary authors may decide focusing the `<dialog>` element itself would provide the best initial focus placement.
When implementing a dialog, it is important to consider the most appropriate place to set user focus. Explicitly indicating the initial focus placement by use of the [autofocus](/en-US/docs/Web/HTML/Global_attributes/autofocus) attribute will help ensure initial focus is set to the element deemed the best initial focus placement for any particular dialog. When in doubt, as it may not always be known where initial focus could be set within a dialog, particularly for instances where a dialog's content is dynamically rendered when invoked, then if necessary authors may decide focusing the `<dialog>` element itself would provide the best initial focus placement. When using {{domxref("HTMLDialogElement.showModal()")}} to open a `<dialog>`, focus is set on the first nested focusable element.

Ensure a mechanism is provided to allow users to close a dialog. The most robust way to ensure all users can close a dialog is to include an explicit button to do so. For instance, a confirmation, cancel or close button as appropriate. Additionally, for those using a device with a keyboard, the <kbd>Escape</kbd> key is commonly expected to close modal dialogs as well. By default, a `<dialog>` invoked by the `showModal()` method will allow for its dismissal by the <kbd>Escape</kbd>. A non-modal dialog does not dismiss via the <kbd>Escape</kbd> key by default, and depending on what the non-modal dialog represents, it may not be desired for this behavior. If multiple modal dialogs are open, <kbd>Escape</kbd> should only close the last shown dialog.
Ensure a mechanism is provided to allow users to close a dialog. The most robust way to ensure all users can close a dialog is to include an explicit button to do so. For instance, a confirmation, cancel or close button as appropriate. Additionally, for those using a device with a keyboard, the <kbd>Escape</kbd> key is commonly expected to close modal dialogs as well. By default, a `<dialog>` invoked by the `showModal()` method will allow for its dismissal by the <kbd>Escape</kbd>. A non-modal dialog does not dismiss via the <kbd>Escape</kbd> key by default, and depending on what the non-modal dialog represents, it may not be desired for this behavior. If multiple modal dialogs are open, <kbd>Escape</kbd> should only close the last shown dialog. When using `<dialog>`, this behavior is provided by the browser.

The `<dialog>` element is exposed by browsers similarly to custom dialogs using the ARIA [role="dialog"](/en-US/docs/Web/Accessibility/ARIA/Roles/dialog_role) attribute. `<dialog>` elements invoked by the `showModal()` method will have an implicit [aria-modal="true"](/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-modal), whereas `<dialog>` elements invoked by the `show()` method, or rendered by use of the `open` attribute or changing the default `display` of a `<dialog>` will be exposed as `[aria-modal="false"]`. It is recommended to use the appropriate `showModal()` or `show()` method to render dialogs.

Ensure your dialog implementation doesn't break expected default behaviors and follows proper labeling recommendations.
The `<dialog>` element is exposed by browsers similarly to custom dialogs using the ARIA [role="dialog"](/en-US/docs/Web/Accessibility/ARIA/Roles/dialog_role) attribute. `<dialog>` elements invoked by the `showModal()` method will have an implicit [aria-modal="true"](/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-modal), whereas `<dialog>` elements invoked by the `show()` method, or rendered by use of the `open` attribute or changing the default `display` of a `<dialog>` will be exposed as `[aria-modal="false"]`. When implementing modal dialogs, everything other than the `<dialog>` and its contents should be rendered inert using the [`inert`](/en-US/docs/Web/HTML/Global_attributes/inert) attribute. When using `<dialog>` along with the `HTMLDialogElement.showModal()` method, this behavior is provided by the browser.

## Usage notes

- {{HTMLElement("form")}} elements can close a dialog if they have the attribute `method="dialog"`. When such a form is submitted, the dialog closes with its {{domxref("HTMLDialogElement.returnValue", "returnValue")}} property set to the `value` of the button that was used to submit the form.
- The {{cssxref('::backdrop')}} CSS pseudo-element can be used to style behind a `<dialog>` element when the dialog is displayed with {{domxref("HTMLDialogElement.showModal()")}}. For example, to dim unreachable content behind the modal dialog.
- {{HTMLElement("form")}} elements can close a `<dialog>` if they have the attribute `method="dialog"` or if the button used to sumbit the form has `formmethod="dialog"` set. In this case, the state of the form controls are saved, not sumbitted, the `<dialog>` closes, and the {{domxref("HTMLDialogElement.returnValue", "returnValue")}} property gets set to the `value` of the button that was used to save the form's state.
- The {{cssxref('::backdrop')}} CSS pseudo-element can be used to style the backdrop that is displayed behind a `<dialog>` element when the dialog is displayed with {{domxref("HTMLDialogElement.showModal()")}}. For example, to dim unreachable content behind the modal dialog.

## Examples

### Simple example

The following will render a modeless (non-modal) dialog. The "OK" button allows the dialog to be closed when activated. It is important to provide a mechanism to close a dialog within the `dialog` element. For instance, the <kbd>Esc</kbd> key does not close modeless dialogs by default, nor can one assume that a user will even have access to a physical keyboard (e.g., someone using a touch screen device without access to a keyboard).
The following will render a non-modal, or modal-less, dialog. The "OK" button allows the dialog to be closed when activated.

```html
<dialog open>
Expand All @@ -115,14 +113,18 @@ The following will render a modeless (non-modal) dialog. The "OK" button allows
</dialog>
```

{{EmbedLiveSample("Simple_example", "100%", 200)}}

Because this dialog was opened via the `open` attribute, it is non-modal. In this example, when the dialog is dismissed, no method is provided to re-open it. Opening dialogs via {{domxref("HTMLDialogElement.show()")}} is preferred over the toggling of the boolean `open` attribute.

### Advanced example

This example opens a modal dialog that contains a form, when the "Update details" button is activated.
This example opens a modal dialog when the "Show the dialog" button is activated. The dialog contains a form. Updating the value of the {{HTMLElement('select')}} updates the value of the "confirm" button.

#### HTML

```html
<!-- Simple modal dialog containing a form -->
<!-- A modal dialog containing a form -->
<dialog id="favDialog">
<form method="dialog">
<p>
Expand All @@ -142,51 +144,42 @@ This example opens a modal dialog that contains a form, when the "Update details
</form>
</dialog>
<p>
<button id="updateDetails">Update details</button>
<button id="showDialog">Show the dialog</button>
</p>
<output></output>
```

#### JavaScript

```js
const updateButton = document.getElementById('updateDetails');
const showButton = document.getElementById('showDialog');
const favDialog = document.getElementById('favDialog');
const outputBox = document.querySelector('output');
const selectEl = favDialog.querySelector('select');
const confirmBtn = favDialog.querySelector('#confirmBtn');

// If a browser doesn't support the dialog, then hide the
// dialog contents by default.
if (typeof favDialog.showModal !== 'function') {
favDialog.hidden = true;
/* a fallback script to allow this dialog/form to function
for legacy browsers that do not support <dialog>
could be provided here.
*/
}
// "Update details" button opens the <dialog> modally
updateButton.addEventListener('click', () => {
if (typeof favDialog.showModal === "function") {
showButton.addEventListener('click', () => {
favDialog.showModal();
} else {
outputBox.value = "Sorry, the <dialog> API is not supported by this browser.";
}
});
// "Favorite animal" input sets the value of the submit button
selectEl.addEventListener('change', (e) => {
confirmBtn.value = selectEl.value;
});
// "Confirm" button of form triggers "close" on dialog because of [method="dialog"]
favDialog.addEventListener('close', () => {
outputBox.value = `${favDialog.returnValue} button clicked - ${(new Date()).toString()}`;
outputBox.value = `ReturnValue: ${favDialog.returnValue}.`;
});
```

### Result

{{EmbedLiveSample("Advanced_example", "100%", 300)}}

Note the JavaScript did not include the {{domxref("HTMLDialogElement.close()")}} method. When a form in a dialog is submitted, if the method is `dialog`, the current state of the form is saved, not submitted, and the dialog gets closed.

It is important to provide a mechanism to close a dialog within the `dialog` element. For instance, the <kbd>Esc</kbd> key does not close non-modal dialogs by default, nor can one assume that a user will even have access to a physical keyboard (e.g., someone using a touch screen device without access to a keyboard).

## Specifications

{{Specifications}}
Expand Down