This component is meant for situations where critical information must be
conveyed, and an explicit response is required from the user. It is typically
used for confirmation dialogs, warning messages, error notifications, and
other scenarios where an immediate decision is necessary.
For non-critical dialogs, such as those containing forms or additional
information, use Doggo.Components.build_modal/1 instead.
Maturity: Developing
Usage
<.alert_dialog id="end-session-modal">
<:title>End Training Session Early?</:title>
<p>
Are you sure you want to end the current training session with Bella?
She's making great progress today!
</p>
<:footer>
<.button phx-click="end-session">
Yes, end session
</.button>
<.button phx-click={JS.exec("data-cancel", to: "#end-session-modal")}>
No, continue training
</.button>
</:footer>
</.alert_dialog>
To open the dialog, use the show_modal/1 function.
<.button
phx-click={Doggo.show_modal("end-session-modal")}
aria-haspopup="dialog"
>
show
</.button>
With HTML attributes
command and commandfor are the Invoker Commands API. Unlike the other
two ways, this API needs no JavaScript at all.
<.button command="show-modal" commandfor="end-session-modal">show</.button>
Both attributes are recent, so the hook handles them if the browser doesn't
support them.
Closing
The alert dialog can be closed by:
- using
hide_modal/1,
- using
JS.exec("data-cancel", to: "#end-session-modal"), which is what
the example above uses for its own control, or
- using the close button or
Esc (only if dismissable is set).
Semantics
The dialog is opened with showModal(), so the browser puts it in the top
layer, draws ::backdrop, makes the rest of the document inert and keeps
the focus inside. aria-modal is not rendered, because showModal()
already marks the component as a modal.
Focus
showModal() moves the focus into the dialog to the first element with the
autofocus attribute, or the first focusable element if no element has it.
The alert dialog is not dismissable by default, so the first focusable
element is usually the first control in the :footer slot. In a
dismissable alert dialog, it is the close button. Neither is likely to be
the right element to focus.
Set autofocus on the element that should receive the focus:
<:footer>
<.button phx-click="end-session">Yes, end session</.button>
<.button
autofocus
phx-click={JS.exec("data-cancel", to: "#end-session-modal")}
>
No, continue training
</.button>
</:footer>
In an alert dialog, the focus should move to the least destructive action,
as recommended in the
ARIA Authoring Practices.
CSS
A dialog is hidden until it is opened, so no rule is needed for that. Style
the backdrop with dialog.alert-dialog::backdrop.
Caveats
An alert dialog is not dismissable by default, so it renders
closedby="none" and no close button, which leaves no way to dismiss it
from the component. Provide your own control in the :footer slot.
Keyboard
Esc - close the dialog (only if dismissable is set).