Azalea
Azalea

Dialog

A modal, built on the native <dialog> element — so focus trapping, Escape, inert background and the backdrop are the browser's job, not ours.

Confirm before something irreversible

Root can restart production. Today its approve button fires the moment it is clicked; this is what should be in front of it.

Deploy Etalasse to production?

This restarts the running service. A second admin still has to approve before it executes.

The confirm button carries the verb, never “OK”. Someone who opened this by accident reads the button, not the paragraph — and “Deploy to production” stops a hand that “OK” would not.

A plain dialog

For anything that is not a confirmation.

Deployment abc1234

Etalasse · staging · requested by Ivy

Press Escape, or click the backdrop. Both close it — a modal you cannot dismiss is a trap.

Guidance

Use it when

  • Confirming something irreversible or outward-facing.
  • A short detail view that would lose the page's scroll position if it were a route.

Reach for something else when

  • A form of more than a few fields. That is a page — a modal cannot be linked to or reloaded.
  • Confirming something reversible. A confirm on every action trains people to click through them.
  • Stacking a dialog on a dialog.

Props

PropTypeDefaultDescription
openbooleanControlled. The effect calls showModal()/close() to match.
onClose() => voidFires for Escape and the backdrop too, so parent state can never drift from what the browser shows.
titlestringLabels the dialog for assistive tech.
confirmLabelstringConfirmDialog only. The verb — not “OK”.
tone"danger" | "default""danger"ConfirmDialog only. Styles the confirm button.
loadingbooleanConfirmDialog only. Spinner on confirm, cancel disabled.

Why native

showModal() gives focus trapping, Escape-to-close, inert on the rest of the page and a ::backdrop — all handled by the browser. A hand-rolled div-and-overlay gets those wrong more often than right, and the failures are invisible until someone tries it with a keyboard.