material-dialog

MD3 modal dialog. Wraps a native <dialog> for top-layer + scrim + focus-trap + Esc; opens via data-dialog-target, native command/commandfor, or .show().

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.

Are you sure you want to delete report-2026.pdf? This action cannot be undone.

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.

Get instant alerts on traffic incidents along your saved routes. You can turn this off any time in Settings.

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.

Opened from JavaScript. Try Esc, click on the scrim, or one of the buttons.
This dialog has 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.

56dp margin from the chosen edge. The current position is reflected on the host as 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.

This dialog uses the default MD3 open/close choreography.
This dialog has 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

(none)
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>