Basic — confirm action via data-dialog-target
Click the trigger; the dialog opens with a scrim, traps focus, and returns focus to the trigger on close.
Action buttons close the dialog with a return value via data-dialog-close.
Basic — opened via native command/commandfor
Modern browsers (Chrome 130+, Safari 18.4+) dispatch a CommandEvent on the target.
On older browsers, fall back to data-dialog-target.
Basic — programmatic .show() / .close()
Drives the dialog from JS. Works equally well with Alpine
@click="$refs.d.show()", HTMX hx-on:click, and React/Vue refs.
dismissible="false". Esc and backdrop clicks are ignored —
only the action button closes it.
Basic — custom position (56dp from edges)
Spec allows custom placement on expanded screens. Each chip opens the same dialog at a different corner.
position="…".
Full-screen — header (close + Save) + content
Compact-only per spec. Default close icon-button is in the leading slot; Save sits in actions.
Adaptive — basic on medium+, full-screen on compact
Resize the window across the 600px breakpoint and reopen — the layout swaps between basic and full-screen.
Basic — long content scrolls, headline/actions stay pinned
The dialog itself is capped at calc(100vh - 6rem); only the body scrolls.
Section 1. Please read the following terms carefully before continuing.
Section 2. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Section 3. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
Section 4. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
Section 5. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Section 6. You've reached the end — the action buttons below never scrolled out of view.
Basic — open/close choreography, and quick
Default: dialog slides down while it grows into place (~500ms) and headline/content/actions fade in staggered;
close mirrors it in ~150ms. quick skips all of that — instant show/hide.
quick set — it opens and closes instantly, no choreography.
Basic — slotted <form method="dialog">
Submitting the form closes the dialog with the submitter's value as the return value,
instead of navigating.
Last result
Sample usage
<!-- Trigger via data-dialog-target (any framework, any browser) -->
<material-button label="Delete…" data-dialog-target="confirm"></material-button>
<material-dialog id="confirm" alert headline="Delete file?" icon="delete">
This cannot be undone.
<div slot="actions">
<material-button variant="text" label="Cancel" data-dialog-close></material-button>
<material-button variant="filled" label="Delete" data-dialog-close="confirm"></material-button>
</div>
</material-dialog>
<!-- Or via the native HTML invoker (Chrome 130+, Safari 18.4+) -->
<button command="show-modal" commandfor="confirm">Delete…</button>
<!-- Or programmatically -->
<script>
const dlg = document.getElementById('confirm');
dlg.show(); // or: dlg.open = true
dlg.close('confirm'); // or: dlg.open = false; dlg.returnValue = 'confirm'
dlg.addEventListener('materialDialogClose', e => {
if (e.detail.returnValue === 'confirm') doDelete();
});
</script>
<!-- Full-screen variant: leading slot defaults to a close button -->
<material-dialog variant="full-screen" headline="New event">
<div slot="actions"><material-button label="Save" data-dialog-close="save"></material-button></div>
<form>…</form>
</material-dialog>
<!-- Adaptive: full-screen below 600px, basic above -->
<material-dialog variant="adaptive" headline="Compose">…</material-dialog>
<!-- Custom position (basic only). All edge positions keep 56dp margin. -->
<material-dialog position="top-end" headline="Inbox">…</material-dialog>
<!-- Skip the open/close choreography entirely (instant show/hide) -->
<material-dialog quick headline="Quick dialog">…</material-dialog>