dialog
Modal and drawer. Focus trap, Esc, and top layer — the browser's. Open/close — invoker commands (shimmed while support spreads).
Example
Basic usage
<button commandfor="confirm" command="show-modal">Open</button> <!-- trigger -->
<dialog id="confirm"> <!-- content -->
<button class="close" commandfor="confirm" command="close" aria-label="Close">✕</button>
<header> <!-- header -->
<h2>Are you sure?</h2> <!-- title -->
<p>This cannot be undone.</p> <!-- description -->
</header>
<p>Any body content.</p>
<footer> <!-- footer: right-aligned row -->
<form method="dialog">
<button>Cancel</button>
<button data-variant="primary" value="ok">Confirm</button>
</form>
</footer>
</dialog>
API
Attributes
| Name | Type | Default | Description |
|---|---|---|---|
data-drawer | boolean | false | Turns the dialog into a responsive desktop side sheet and mobile bottom sheet. |
open | native boolean | false | Reflects whether the native dialog is open. Prefer showModal() to open a modal. |
Content/markup contract
| Part | Contract | Default | Description |
|---|---|---|---|
header | direct child | optional | Contains the title and description. |
| Body | one element between header and footer | — | Padded, scrollable content region. |
footer | direct child | optional | Right-aligned actions; drawer actions stack and pin to the bottom. A form method="dialog" closes natively. |
button.close | direct child | optional | Corner dismiss control; provide an accessible name. |
Native methods and values
| Name | Type | Default | Description |
|---|---|---|---|
showModal() | method | — | Opens in the top layer with modal focus and backdrop behavior. |
close() | method | — | Closes the dialog. |
returnValue | string property | "" | Carries the value of the button that submitted a method="dialog" form. |
drawer.js
Optional. Below 40rem the drawer is a content-height, full-width bottom sheet. The module adds a grab handle and swipe-to-dismiss from the handle/header strip: downward drags follow the pointer, upward drags resist, and the sheet closes past one third of its height or on a flick. It also manages the mobile scrim, lightening it during drag and fading it on close, including on iOS. Without the module, open/close, Esc, and the CSS-only scrim still work; no handle appears.
<script type="module" src="mica/drawer.js"></script>On mobile the handle is the dismiss affordance, so you may hide the redundant corner close button:
@media (max-width: 40rem) {
dialog[data-drawer] > button.close { display: none; }
}invoker.js
Temporary optional shim for the recipe's show-modal and close invoker commands. It installs nothing when commands are native.
<script type="module" src="mica/invoker.js"></script>Accessibility
Native modal dialogs provide top-layer behavior, focus trapping, Esc dismissal, and backdrop handling. Give icon-only close buttons an accessible name. Use a heading and description in the header so the purpose is clear.
Browser support
Invoker commands (commandfor/command) are Baseline newly-available (Chrome 135+, Firefox 144+, Safari 26.2+). Include invoker.js until they are widely available. The shim's removal is a one-line diff.
Notes
Enter/exit animations use @starting-style and transition-behavior: allow-discrete. Standard modal backdrops fade where the engine supports top-layer exit transitions.