Skip to content

Conversation

@klnusbaum
Copy link

@klnusbaum klnusbaum commented Dec 26, 2025

This adds a Dialog example using the standard HTML dialog.

Description

I noticed that while there were several examples around how to make modal dialogs, none of them actually used the <dialog> tag. I was curious if I could actually get htmx to work with the <dialog> tag and after some playing around, I was able to get something that works. I figured it might be good to share what I learned.

I'm not entirely sure this is a good idea. The more I learn about html dialogs, the more I'm skeptical about how useful they are. I'm curious what others think.

Testing

Ran the docs locally and verified the intended behavior.

Checklist

  • I have read the contribution guidelines
  • I have targeted this PR against the correct branch (master for website changes, dev for
    source changes)
  • This is either a bugfix, a documentation update, or a new feature that has been explicitly
    approved via an issue
  • I ran the test suite locally (npm run test) and verified that it succeeded

This adds a Dialog example using the standard HTML dialog.
@klnusbaum klnusbaum changed the title HTML Dialog Example Docs: HTML Dialog Example Dec 26, 2025
hx-swap="outerHTML"
>Open Modal</button>

<div id="modal-placeholder"></div>
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My intuition tells me there should be an easier way to do this, without needing this place holder div. But without, there's nothing to do an "outerHTML" swap with. And without that "outerHTML" swap, the hx-on::after-settle doesn't get called on the dialog. For example, if we have the button target the <body> and do a hx-swap="beforeend", then its the body that gets the hx-on::after-settle event.

I think for Locality-of-behavior reasons, it's best to have the call to showModal on the dialog itself. So that's why I went with this. Happy to entertain other ideas.

@marcoklein
Copy link

Would be interesting to have that in the docs. Were you able to solve that client side ESC closing mechanism? As the docs state a modal can be closed via Escape and then HTMX looses control over the state as it's closed client side but not yet replaced.

In your example I could produce that behaviour by opening the modal and pressing Escape. I got it working for another use-case by returning <dialog open ...></dialog> because then it doesn't open in the modal state and does not have that default closing mechanism.

1. Fix a couple typos
2. Change the dialog to use `closedby="none"`
@klnusbaum
Copy link
Author

klnusbaum commented Jan 6, 2026

Would be interesting to have that in the docs. Were you able to solve that client side ESC closing mechanism? As the docs state a modal can be closed via Escape and then HTMX looses control over the state as it's closed client side but not yet replaced.

In your example I could produce that behaviour by opening the modal and pressing Escape. I got it working for another use-case by returning <dialog open ...></dialog> because then it doesn't open in the modal state and does not have that default closing mechanism.

The HTML spec seems to strongly discourage the use of the open attribute, so I tried to stay away from it. I got something working by setting closedby="none". This makes it so the only way to close the dialog is by clicking out button.

It doesn't feel great.

The other thing I tried doing was setting an hx-trigger to listen for the escape key. But I couldn't get that to work.

Overall, given the number of caveats we seem to need for this example, I'm not sure I like this. Feels like I'm trying to ice-skate uphill.

@klnusbaum
Copy link
Author

After reading the HTML spec a little more closely, the objections it has to using the open attribute seemed like the didn't apply in this case. I gave it a shot and it produced some weirdness where the dialog wasn't centered in the page. It was buried down in the footer and I had to scroll to find it. I'm not sure what that's all about.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants