1
Fork 0
modal-dialog/README.md
Leonardo Devai 3a0dc902e5 Review and modernize all 42 projects to the updated standard
Pinned 2026 toolchains (Go 1.26, Rust 1.98/edition 2024, Python 3.14 + uv, Node 24,
Zig 0.16, NixOS 26.05), postgres 18 / mongo 8, lockfiles built from, non-root
runtimes, .dockerignore, per-project LICENSE, READMEs with the git.devai.io clone
line, checkout@v7 CI. Security fixes in the legacy Rust APIs (any-password login,
self-assigned admin, hard-coded JWT secret), JWT alg/exp/sub enforcement across the
blog series, safe markdown links in the frontends, and many smaller bugs — every
project was built, run and exercised end to end.

Adds scripts/publish.sh + a CI publish job that splits every folder into its own
repo at git.devai.io/templates/<folder>.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01128fhuZbgivaSJvtMf4s1G
2026-09-27 21:10:38 +02:00

59 lines
2.1 KiB
Markdown

# modal-dialog
A pop-up done the modern way — with the browser's built-in `<dialog>` element
instead of a pile of hand-rolled JavaScript. Open it, then close it with a
button, the Escape key, or a click on the dimmed backdrop.
## Run
Get it: `git clone https://git.devai.io/templates/modal-dialog.git`
Double-click `index.html` — it opens in your browser and works. Nothing to
install, no build step.
Or serve it like production:
```sh
docker compose up --build
```
Then open http://localhost:8080.
## How it works
`dialog.showModal()` does the hard parts for you: it paints a `::backdrop`
behind the dialog, makes the rest of the page inert (no clicking or tabbing
behind it), moves keyboard focus inside, closes on Escape, and returns focus to
the button that opened it. Hand-built modals need dozens of lines for that.
- **Closing on purpose:** `dialog.close("ok")` closes it and records why in
`dialog.returnValue`. The code clears that value on every open, so an empty
one afterwards means the user pressed Escape.
- **Backdrop click:** a click on the backdrop lands on the `<dialog>` element
itself. The dialog has no padding and its inner `.dialog-body` fills it, so
`event.target === dialog` means "clicked outside the box".
- **One `close` event** fires however it closed, and the status line reports why.
Try it: add a "Cancel" button with its own `returnValue`, turn it into a
confirm box that only acts when `returnValue === "ok"`, or animate
`.dialog[open]` with CSS.
## Layout
```
index.html the open button, and the <dialog> with its inner .dialog-body
app.js open, close, backdrop click and the close event
styles.css the dialog and its ::backdrop; follows light or dark mode
```
## Deploy
Push to your own GitHub repo and the shipped workflow
(`.github/workflows/ci.yml`) tests the compose stack, publishes the image to
GHCR, and — once you set the `DEPLOY_HOST` / `DEPLOY_USER` variables and
`DEPLOY_KEY` secret — deploys it to your server over ssh.
---
Part of [devai.io](https://devai.io) — the Web Basics track: HTML, CSS &
JavaScript, one concept at a time. Next up:
[star-rating](https://git.devai.io/templates/star-rating).