HTML dialog
https://www.youtube.com/watch?v=1Op2ZdYGaGA
https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dialog
Simplest setup
<dialog data-dialog-target="dialog" open > <div class="bg-red-50 p-5"> <form method="dialog"> <button formmethod="dialog">Close</button> </form> <hr> <form src="/foo" method="post"> <button>Submit</button> <button formmethod="dialog">Close</button> </form> </div> </dialog>
Stimulus JS open dialog as Modal
// app/javascript/controllers/dialog_controller.js import { Controller } from "@hotwired/stimulus" // Connects to data-controller="dialog" export default class extends Controller { static targets = [ "dialog" ] open() { this.dialogTarget.showModal() document.body.classList.add("overflow-hidden") } close() { document.body.classList.remove("overflow-hidden") this.dialogTarget.close() } clickOutside(event) { if (event.target === this.dialogTarget) { this.close(); } } }
<body> ... <div data-controller="dialog" data-action="click->dialog#clickOutside"> <button data-action="click->dialog#open">Open Dialog</button> <dialog data-dialog-target="dialog" class=" w-full lg:w-1/3"> <div class="bg-red-50 p-5"> <button data-action="click->dialog#close">X</button> <form src="/foo" method="post"> <button>submit</button> </form> </div> </dialog> </div> ... </body>
// app/assets/stylesheets/application.css dialog::backdrop { backdrop-filter: blur(10px); }
alternative: you can style <dialog class="backdrop:bg-slate-400 backdrop:opacity-80"> with tailwind
Stimulus JS opens dialog non-modally (ideal for dropdowns, searchboxes)
// app/javascript/controllers/dialog_controller.js import { Controller } from "@hotwired/stimulus" // Connects to data-controller="dialog" export default class extends Controller { static targets = [ "dialog", "open" ] open() { this.dialogTarget.show() } close() { this.dialogTarget.close() } clickOutside(event) { if (!this.dialogTarget.contains(event.target) && event.target != this.openTarget) { this.close(); } } }
<body data-controller="dialog" data-action="click->dialog#clickOutside"> <dialog data-dialog-target="dialog" class="w-full md:w-3/4 lg:w-2/3"> <div class="bg-red-50 p-5"> <button data-action="click->dialog#close">X</button> <form src="/foo" method="post"> <button>submit</button> </form> </div> </dialog> <button data-action="click->dialog#open" data-dialog-target="open">Open Dialog</button> <body>