Skip to content

Dialog JS

scss
@use '@natachah/vanilla-frontend/scss/components/dialog';

Difference between modal and non-modal:

The key difference is the level interaction and interaction restriction. A modal will block interaction with the main content, and they have their own context focus (use of a backdrop). But a non-modal don't impose context and restriction.

Syntax

The dialog is using the native <dialog> tag.

You can define if the dialog is a modal with the aria-modal attribute.

html
<button aria-controls="myDialog">Open the dialog</button>
<dialog id="myDialog" aria-modal="true" aria-label="demo">
    Content of the dialog
    <button data-dialog-close>Close the dialog</button>
</dialog>
css
--dialog-color
--dialog-background
--dialog-border-size
--dialog-border-style
--dialog-border-color
--dialog-border-radius
--dialog-padding-inline
--dialog-padding-block
--dialog-position
--dialog-width
--dialog-height
--dialog-max-width
--dialog-max-height
--dialog-index
--dialog-backdrop-background
--dialog-backdrop-filter
--dialog-open-animation
--dialog-open-transform
--dialog-close-animation
--dialog-close-transform
--dialog-divider-size
--dialog-divider-style
--dialog-divider-color
js
import Dialog from "@natachah/vanilla-frontend/js/_dialog"
const myDialog = document.getElementById('myDialog')
if (myDialog) new Dialog(myDialog)

To work properly you must have a <button> in your page with the attribute aria-controls="IdOfDialogToOpen" that will open the dialog.

And inside your <dialog> you should have a <button> with the attribute data-dialog-close to close the dialog.

For accessibility, don't forget to add a aria-labelledby into the <dialog> to set a title.

Layout

The dialog can have a <header> and/or <footer> inside to create a more complexe layout.

html
<dialog id="layoutDialog" aria-labelledby="layoutDialogTitle" aria-modal="true">
    <header id="layoutDialogTitle">This is a header</header>
    <div>
        <p>This is the content</p>
        <button data-dialog-close>Close</button>
    </div>
    <footer>This is a footer</footer>
</dialog>

Form

You can submit a <form> inside the <dialog>.

html
<dialog id="formDialog" aria-labelledby="formDialogTitle" aria-modal="true">
    <h3 id="formDialogTitle">Dialog with form</h3>
    <form method="POST">
        <label for="animal">What is your favorite animal</label>
        <input id="animal" type="text" name="animal" required>
        <button type="reset" data-dialog-close>Cancel</button>
        <button type="submit">Default submit</button>
    </form>
</dialog>

If you want to submit via javascript add the method="dialog" attribute on the <form> or the formmethod="dialog" attribute on the <button>.

Then you should use the event dialog:submited to catch the values.

html
<button aria-controls="jsDialog">Open the dialog</button>
<dialog id="jsDialog" aria-labelledby="jsDialogTitle" aria-modal="true">
    <h3 id="jsDialogTitle">Dialog with form</h3>
    <form method="dialog">
        <label for="animal">What is your favorite animal</label>
        <input id="animal" type="text" name="animal" required>
        <button type="reset" data-dialog-close>Cancel</button>
        <button type="submit">Javascript submit</button>
    </form>
</dialog>
<p>Your favorite animal is: <span id="favorite">--</span></p>
js
const demoDialogFormJS = document.getElementById('jsDialog')

if (demoDialogFormJS) {

    // Init the dialog
    new Dialog(demoDialogFormJS)

    // Check for the dialog:submited event
    demoDialogFormJS.addEventListener('dialog:submited', (e) => {
        const value = e.detail.form.querySelector('input').value
        document.getElementById('favorite').innerText = value
    })

}

Javascript

To work properly the dialog required some javascript.

Methods

MethodDescription
open(e)This method will open the dialog
close()This method will close the dialog
submit()This method will submit the dialog

Events

Event nameDescriptionValue
dialog:openingWhen the method open() is called
dialog:openedAfter the method open() is called
dialog:closingWhen the method close() is called
dialog:closedAfter the method close() is called
dialog:submitingWhen the method submit() is calledform as an HTMLElement
dialog:submitedAfter the method submit() is calledform as an HTMLElement
js
// E.G. basic opening
document.getElementById('myDialogID').addEventListener('dialog:opening', () => {
    console.log('The dialog is opening')
})

// E.G. with form value
document.getElementById('myDialogID').addEventListener('dialog:submited', (e) => {
    const theHTMLForm = e.detail.form
    console.log('The dialog is submited')
})

Released under the MIT License.