Dialog
Excerpts from Mary Shelley's Frankenstein (1818). Animation, dragging and
reparenting have their own guides: animate-to-from-top-layer, drag,
persistent-top-layer-ui.
1. Modal confirmation (declarative)
command="show-modal", aria-labelledby,
<form method="dialog">, autofocus on the safe action.
2. Modal form with returnValue
A close listener reads dialog.returnValue, then resets it. Pressing
Esc sets no value, so it reads "" (dismissed) instead of the previous button. Closing
returns focus to the trigger.
3. closedby="any" (light dismiss)
Clicking the backdrop closes it natively. Where closedby is unsupported, a feature-tested
pointer fallback does the same.
4. closedby="none" with unsaved changes
Cancel uses request-close, so the cancel handler can ask for
confirmation: it shows a message and focuses Discard, which references the message with
aria-describedby so a screen reader reads it. Discard appears where no button moves, so a second
click on Cancel cannot discard. Only the developer-controlled Discard button force-closes.
5. Non-modal <dialog popover>
Top layer, page stays interactive, visible close button.
6. Non-modal dialog.show()
For contrast: not in the top layer, no backdrop, and closedby defaults to
none, so this one opts in with closedby="any". Use it only when the panel must not be in
the top layer.
7. Plain [popover] for a menu
Not everything is a dialog: no modality, no focus trap, just light-dismiss.