<dialog> demo<dialog> element.
htmx swaps it into the DOM via hx-swap="outerHTML".
A 7-line shim calls showModal() on any <dialog data-modal> that arrives.
All close interactions use native <form method="dialog"> — zero JS.
command="show-modal" reaches ~95% adoption,
delete dialog-shim.js and add commandfor/command="show-modal"
to the trigger buttons. The rest stays identical.
First open: hx-target="body" hx-swap="beforeend" — appends dialog to body.
Subsequent: hx-target="#drupal-dialog" hx-swap="outerHTML" — replaces in place.
closedby="any"Native Chrome 133+, Firefox 136+. Shim polyfills for Safari via a delegated click listener.
Server sets open attribute directly. No shim involvement.
Server sets data-persist on the <dialog>. Close removes it from view but not the DOM — reopen with no fetch.
Target the existing #drupal-dialog with hx-swap="outerHTML".
Server returns a new <dialog data-modal> — shim calls showModal() again.
Server returns a fragment that removes #drupal-dialog from the DOM.
role="alertdialog"Server sets role, aria-labelledby, aria-describedby directly on <dialog>.
command="show-modal"No shim. Chrome 135+ only (~65% today). Shows what the zero-JS future looks like.