Dialog

A modal window for a focused task, with a title, body, footer actions and managed focus.

<tp-dialog>
Dialog
Default density Compact density Restart from the initial state Show the copyable source
Edit profile
Save changes

Usage

Put the opening Button in the trigger slot and the task in the default slot. label and description become the visible title and description and name the dialog for assistive technology. The Dialog moves focus inside on open, keeps the rest of the page inert and returns focus to the trigger on close.

Use Alert Dialog instead when the user must confirm a consequential decision.

The first element in the close slot closes the dialog when activated. Anything in footer is ordinary content with no close behavior, which suits secondary actions such as copying a link that should keep the dialog open. For other placement, call dialog.registerCloseAction(button) and retain the returned cleanup function. Empty footers are hidden.

Footer and close
Default density Compact density Restart from the initial state Show the copyable source
Invite teammates Copy invite link Send invites

The corner Close stays visible unless another named close action is reachable, so a dialog can always be dismissed.

Modality

modality="non-modal" leaves the page interactive and scrollable behind the dialog. Use it for reference content, such as a shortcut list, that people read while they keep working.

Non-modal
Default density Compact density Restart from the initial state Show the copyable source
Keyboard shortcuts
Search
K
New document
N
Toggle sidebar
B

Contained in a region

modality="container" makes the dialog modal within one region instead of the whole page. Assign that region to the container property: the dialog renders inside it, makes only the region’s other content inert and leaves the rest of the page interactive. Give the region position: relative and isolation: isolate.

While open, the dialog:

  • renders inside the container instead of the native top layer, so it is clipped to the container and stays visible while the container is fullscreen;
  • makes only the container’s other content inert; content outside the container stays interactive;
  • traps Tab focus within the dialog; like document modality it never pulls back focus that moves elsewhere, so overlays another owner adds (such as autofill menus) stay usable;
  • does not lock page scroll;
  • sizes its Overlay to the container and centers and bounds Content within it;
  • handles Escape and close requests only while focus is inside the container, and uses the usual initial and final focus. Final focus is not restored when the user has already moved focus outside the container;
  • exposes aria-modal="false", because the rest of the document remains available. The container’s inert siblings carry the isolation.

Outside presses within the container hit the Overlay and follow closeOnOutsideInteraction; presses outside the container never dismiss.

Container modality
Default density Compact density Restart from the initial state Show the copyable source
Invoice INV-2048 Simulate timeout Sign in again

The rest of the page stays usable while the dialog is open.

Without a usable container the dialog falls back to page-wide modal. Drawer does not support container. Alert Dialog supports modal and container.

Backdrop

backdrop="blur" keeps the dark fill and blurs the page behind it, which suits a focused task over a busy screen. It changes only the appearance; modality still decides whether there is a backdrop at all. Drawer and Alert Dialog accept the same attribute.

Blurred backdrop
Default density Compact density Restart from the initial state Show the copyable source
Share Done

Detached triggers

When the opening control lives elsewhere, such as a table row or a menu, register it with registerTrigger(). It toggles the dialog and receives focus on close, just like a slotted trigger.

Registered trigger
Default density Compact density Restart from the initial state Show the copyable source
Rename “Q3 planning” Rename

Confirming close

tp-open-change is cancelable. Prevent it to keep the dialog open, for example while a draft still has unsaved text.

Veto closing
Default density Compact density Restart from the initial state Show the copyable source
Write a comment Post comment

Here the close action still posts, while Escape and outside presses are refused until the text area is empty.

Anatomy and presentation

Section spacing comes from one variable. Set --tp-dialog-spacing (a length, normally a --tp-space-* role; default --tp-space-4) on the Dialog, or on Content through its part hook, to change the header, body and footer inset together. --tp-dialog-spacing: 0 gives an edge-to-edge body for compositions that bring their own layout, such as a settings dialog with a navigation panel. A visible corner Close without a header still keeps its own row. Drawer and Alert Dialog read the same variable.

Default motion runs on opening only. Accepted closing removes the surface and backdrop immediately, without waiting for an exit transition. A consumer may explicitly claim the backdrop exit through tp-motion-request to provide its own animation and completion. The portal wrapper contributes no layout box beside the trigger.

API Reference

Every element also accepts motion-policy.

Attributes

AttributePropertyTypeDefaultDescriptionopenopenboolean—Whether the dialog is open; set it to open or close from code without a proposal.default-opendefaultOpenbooleanfalseOpens the dialog when it first connects, when open is not set.keep-mountedkeepMountedbooleanfalseKeeps the content in the document after closing, hidden.close-on-escapecloseOnEscapebooleantrueWhether Escape proposes closing.modalitymodalityDialogModality—Requested modality. container scopes modality to container; when that cannot apply, the document modality is used with a diagnostic. Values a family member does not support normalize to modal.close-on-outside-interactioncloseOnOutsideInteractionboolean—Whether a press or focus outside the dialog proposes closing.show-close-controlshowCloseControlbooleantrueWhether the corner Close button always shows; when false it still shows unless another close action is reachable.portalportalbooleanfalseRenders the dialog into a container at the end of the document, out of clipping or stacking ancestors.portal-identifierportalIdentifierstring | undefined—Identifier of a shared portal container, for dialogs that should render into the same one.show-headershowHeaderbooleantrueWhether the header with the title and the description shows; hidden, they still name the dialog.show-footershowFooterbooleantrueWhether the footer shows.initial-focusinitialFocusDialogInitialFocus'first'Where focus goes on open: the first control, the popup itself, an element or a selector, or a resolver that receives how the dialog was opened.labellabelstring''The visible title, which also names the dialog for assistive technology.descriptiondescriptionstring''The visible description, announced with the title.force-renderforceRenderbooleanfalseDraws its own backdrop when opened from another dialog, which otherwise shows only its parent's.backdropbackdrop'dark' | 'blur''dark'Overlay treatment: a dark fill, or the same fill blurring what it covers.trigger-identifiertriggerIdentifierstring | undefined—Identifier of the registered trigger the dialog belongs to while open; it opens only for that trigger.default-trigger-identifierdefaultTriggerIdentifierstring | undefined—Identifier of the trigger a dialog opened by default-open belongs to.

Properties

PropertyTypeDefaultDescriptionfinalFocusDialogFinalFocus'trigger'Where focus returns on close: the trigger, the previous focus, an element, a resolver, or false to leave it.containerOwnedPortalContainernullThe element the dialog renders into: the portal container, or the region that container modality scopes to.onOpenChange((event: TpSurfaceOpenChangeEvent) => void) | undefined—Called with each open or close proposal before tp-open-change is dispatched.onOpenChangeComplete((open: boolean) => void) | undefined—Called after the dialog finishes opening or closing.handleDialogHandle | undefined—A handle from createDialogHandle() that opens the dialog from triggers registered elsewhere, with a payload each.actionsread-onlyobject{ close: () => this.close(), unmount: () => this.unmount() }The close and unmount actions, for code that should not hold the dialog itself.effectiveModalityread-onlyDialogModality—The modality currently applied after resolving container (see modality).payloadread-onlyunknown—The payload of the trigger or handle call that opened the dialog.activeTriggerIdentifierread-onlystring | undefined—Identifier of the trigger that opened the dialog.

Events

EventTypeDescriptiontp-open-changeTpSurfaceOpenChangeEventCancelable proposal to open or close, before the dialog changes; detail.value is the proposed state and detail.reason what asked (trigger-press, close-action, escape-key, outside-press, imperative-action and others). On a close, detail.preventUnmountOnClose() keeps the content mounted.tp-open-change-completeCustomEvent<{ open: boolean; }>After the dialog finishes opening or closing; detail.open.

Methods

MethodReturnsDescriptionregisterTrigger(element, options)() => voidMakes an element elsewhere in the document a trigger: it opens the dialog and receives focus on close. Returns a cleanup function.setOpen(open, reason, sourceEvent?)voidProposes opening or closing, with the reason the proposal carries.close()voidProposes closing, as a close action would.unmount()voidRemoves content kept mounted after closing, closing first when open.registerCloseAction(element)() => voidBind a consumer-owned, named action wherever it is composed in this surface.

Slots

SlotDescriptiondefaultThe body of the task.triggerThe control that opens the dialog, usually a Button.titleThe title, in place of label.descriptionThe description, in place of description.footerFooter content with no close behavior, such as a secondary action.closeAn action that closes the dialog when pressed, after its own handlers.

CSS parts

PartDescription::part(dialog)The host around the trigger and the dialog.

Components, widgets and patterns that use this one.