HomeGetting StartedColor SystemTypographySpacingIconographyLayoutInstallationUsageAngularBlazorReactSvelteVueThemingTypographyCustomizationCSS-Only ComponentsFormsIconsIllustrationsAccessibilityGlobal ConfigurationTailwind CSSSass LibraryForge MCP ServerDropdown OptionsFocus Indicator ClippingAll componentsButtonButton AreaChipFloating Action ButtonIcon ButtonSplit ButtonAutocompleteButton ToggleCalendarCheckboxChip FieldColor PickerDate PickerDate Range PickerFile PickerLabelRadioSelectSliderSwitchText FieldTime PickerApp BarApp LauncherDrawerMenuPaginatorSkip LinkStepperTabsView SwitcherAccordionApp LayoutCardDividerExpansion PanelScaffoldSplit ViewStackStructured CardToolbarBadgeBannerBusy IndicatorCircular ProgressDialogInline MessageLinear ProgressPage StateSkeletonToastTooltipAvatarIconKeyLabel ValueListMeterSecretTableTimelineTimestampTreeKeyboard ShortcutPopoverIntroductionColorTypographySpacingShapeBorderElevationLayeringAnimationUsageIcon LibraryBlocksRoadmapChangelogBlog

Dialog

Dialogs are modal windows that interrupt the user to convey critical information or request a decision.

Open dialog

Usage

forge-dialog shows modal (or non-modal) content through open, mode, type, preset, placement, fullscreen, and persistent, and typically composes with a forge-scaffold’s header/body/footer slots for structure. Use it sparingly, only for critical information or a decision that truly needs to block the rest of the app. For the common confirm/cancel prompt, reach for the pre-built forge-confirmation-dialog instead of hand-building one. For lower-priority feedback, use a toast, banner, or inline message instead.

Rules

Do
Reserve a dialog for critical information or a decision that truly needs to block the rest of the app.Use a filled button for the confirming action and a tonal button for the dismissive one, with the confirming action on the right.Disable the confirming action until every required field in the dialog is filled.Confirm before discarding unsaved changes when a user tries to close a dialog containing form input.
Don't
Don't stack a dialog on top of another dialog.Don't let a click outside the dialog close it when the dialog contains a form — that risks accidental data loss.Don't place two filled buttons next to each other in a dialog's footer.Don't use a vague action label like "OK" or "Done" — use a specific verb like "Save" or "Send".

Structure

A dialog’s content is typically a forge-scaffold with a header toolbar (title plus a close icon button), a body (the message or form), and a footer toolbar (actions) — pinning the header and footer so only the body scrolls. The title goes in the header toolbar’s start slot and the close icon button in its end slot. The footer toolbar sets inverted so its divider sits above it.

<forge-dialog labelledby="edit-profile-title">
  <forge-scaffold>
    <forge-toolbar slot="header">
      <h2 slot="start" id="edit-profile-title" class="forge-typography--heading3">Edit profile</h2>
      <forge-icon-button slot="end" density="medium" aria-label="Close dialog">
        <forge-icon name="close"></forge-icon>
      </forge-icon-button>
    </forge-toolbar>
    <div slot="body" class="p-medium">...</div>
    <forge-toolbar slot="footer" inverted>
      <div slot="end" class="flex items-center gap-medium">
        <forge-button variant="tonal">Cancel</forge-button>
        <forge-button variant="filled">Save</forge-button>
      </div>
    </forge-toolbar>
  </forge-scaffold>
</forge-dialog>

A dialog built from a scaffold's header, body, and footer slots.

Opening a dialog

Set open on a dialog already in the page to show it, and remove it (or set open = false) to close it. To create one on demand, build it in script, append it to document.body, then set open:

const dialog = document.createElement("forge-dialog");
dialog.label = "Edit profile";
dialog.append(content);
document.body.append(dialog);
dialog.open = true;

In Angular apps, open dialogs through DialogService from @tylertech/forge-angular instead of creating the element yourself.

Modes

mode controls how a dialog sits relative to the rest of the page. modal (the default) renders above everything with a backdrop and makes the rest of the page inert. nonmodal renders in the normal page flow, above other content, with no backdrop and nothing made inert. inline-modal is the middle ground — a backdrop is shown, but unlike modal, the rest of the page is not made inert.

Prevent close

Listen for forge-dialog-before-close and call event.preventDefault() to block a close — useful for validating input or waiting on an async save before letting the dialog close. This event only fires for light-dismiss actions (clicking the backdrop or pressing Escape), not for an explicit close triggered from your own button.

dialogEl.addEventListener("forge-dialog-before-close", (event) => {
  if (!formIsValid) {
    event.preventDefault();
  }
});

Confirmation dialog

For the common confirm/cancel prompt, use the pre-built forge-confirmation-dialog instead of hand-building a scaffold — it handles the title, message, and button slots for you.

A pre-built confirmation dialog handles the title, message, and button slots.

Listen for forge-confirmation-dialog-action to handle the result. detail.value is true when the user clicks the primary button, and false when they click the secondary button or press Escape (detail.reason is 'light-dismiss'). The dialog closes on its own afterward. To keep it open while an async action runs, call preventDefault() and set isBusy, then close it yourself when the action finishes.

confirmationDialog.addEventListener("forge-confirmation-dialog-action", async (event) => {
  if (!event.detail.value) {
    return;
  }
  event.preventDefault();
  confirmationDialog.isBusy = true;
  await deleteRecord();
  confirmationDialog.open = false;
});

Presets

Looking for Bottom Sheet?

Bottom Sheet is now a Dialog preset rather than its own component — use preset="bottom-sheet" below instead.

Set preset to bottom-sheet, top-sheet, left-sheet, or right-sheet to slide the dialog in from an edge instead of the default, centered dialog preset — common on mobile.

Bottom sheet

A dialog sliding in from the bottom of the screen.

Top sheet

A dialog sliding in from the top of the screen.

Left sheet

A dialog sliding in from the left edge of the screen.

Right sheet

A dialog sliding in from the right edge of the screen.

Fullscreen

Set fullscreen (or let fullscreenThreshold trigger it automatically below a given viewport width) to expand the dialog to fill the screen — use it for a multi-step task, like a form paired with a stepper, and reserve it for mobile.

A fullscreen dialog fills the entire viewport.

Dialogs are temporary UI elements that are used to display information, ask for input, or confirm actions. Dialogs can be modal or non-modal.

import "@tylertech/forge/dialog";
Properties
PropertyAttributeTypeDefaultDescription
openopenunknownfalseIndicates whether the dialog is open.
modemodeDialogMode'modal'The mode of the dialog.
typetypeDialogType'dialog'The type of the dialog.
animationTypeanimation-typeDialogAnimationType'zoom'The animation type of the dialog.
presetpresetDialogPreset'dialog'The preset design that the dialog will apply.
persistentpersistentunknownfalseIndicates whether the dialog is dismissible via escape and backdrop click or not.
fullscreenfullscreenunknownfalseIndicates whether the dialog is fullscreen or not.
fullscreenThresholdfullscreen-thresholdunknown599The screen width at which the dialog will switch to fullscreen.
triggertriggerunknown''The selector of the element that triggers the dialog.
triggerElement—HTMLElement | nullnullThe element that triggers the dialog.
moveablemoveableunknownfalseIndicates whether the dialog is moveable or not.
positionStrategyposition-strategyDialogPositionStrategy'viewport'Controls whether the dialog is rendered relative to the viewport or its nearest containing block.
sizeStrategysize-strategyDialogSizeStrategy'content'Controls the block and/or inline size of the dialog. Defaults to the size of the content it contains.
placementplacementDialogPlacement'center'The placement of the dialog.
labellabelunknown''The accessible label of the dialog.
descriptiondescriptionunknown''The accessible description of the dialog.
labelledBy—string | string[] | nullnullThe id or ids of elements in the dialog's root node that label the dialog. Takes precedence over `label`. Use this to associate elements by id across the shadow boundary.
describedBy—string | string[] | nullnullThe id or ids of elements in the dialog's root node that describe the dialog. Takes precedence over `description`. Use this to associate elements by id across the shadow boundary.
labelledByElements—Element[] | nullnullThe elements that label the dialog. Takes precedence over `labelledBy` and `label`.
describedByElements—Element[] | nullnullThe elements that describe the dialog. Takes precedence over `describedBy` and `description`.
—labelledbystring | string[] | nullnullThe id or ids of elements in the dialog's root node that label the dialog. Takes precedence over `label`. Use this to associate elements by id across the shadow boundary.
—describedbystring | string[] | nullnullThe id or ids of elements in the dialog's root node that describe the dialog. Takes precedence over `description`. Use this to associate elements by id across the shadow boundary.
Events
NameTypeDescription
CustomEvent
forge-dialog-openCustomEvent<void>Dispatched when the dialog is opened.
forge-dialog-closeCustomEvent<void>Dispatched when the dialog is closed.
forge-dialog-before-closeCustomEvent<IDialogBeforeCloseEventData>Dispatched before the dialog is closed. This event is cancelable.
forge-dialog-move-startCustomEvent<IDialogMoveStartEventData>Dispatched when the dialog is first moved.
forge-dialog-moveCustomEvent<IDialogMoveEventData>Dispatched when the dialog is being moved.
forge-dialog-move-endCustomEvent<void>Dispatched when the dialog is done being moved.
forge-dialog-fullscreen-changeCustomEvent<boolean>Dispatched when the dialog's fullscreen state changes.
Slots
NameDescription
(default)The content of the dialog.
move-handleThe move handle content.
CSS Parts
NameDescription
::part(root)The dialog container element.
::part(backdrop)The backdrop element.
::part(surface)The dialog surface element.
::part(move-handle-container)The alignment container for the move handle.
::part(move-handle)The move handle element.
::part(move-handle-icon)The move handle icon element.
CSS Custom Properties
NameDescription
--forge-dialog-backgroundThe background color of the dialog.
--forge-dialog-shapeThe shape of the dialog.
--forge-dialog-elevationThe elevation of the dialog.
--forge-dialog-spacingThe spacing between elements inside the dialog.
--forge-dialog-block-start-spacingThe spacing at the start of the dialog block.
--forge-dialog-block-end-spacingThe spacing at the end of the dialog block.
--forge-dialog-inline-start-spacingThe spacing at the start of the dialog inline.
--forge-dialog-inline-end-spacingThe spacing at the end of the dialog inline.
--forge-dialog-paddingThe padding of the dialog.
--forge-dialog-widthThe width of the dialog.
--forge-dialog-heightThe height of the dialog.
--forge-dialog-min-widthThe minimum width of the dialog.
--forge-dialog-max-widthThe maximum width of the dialog.
--forge-dialog-min-heightThe minimum height of the dialog.
--forge-dialog-max-heightThe maximum height of the dialog.
--forge-dialog-z-indexThe z-index of the dialog.
--forge-dialog-move-handle-colorThe color of the move handle.
--forge-dialog-move-handle-sizeThe size of the move handle.
--forge-dialog-move-handle-hover-cursorThe cursor style when hovering over the move handle.
--forge-dialog-move-handle-active-cursorThe cursor style when the move handle is active.
--forge-dialog-move-handle-spacingThe spacing around the move handle.
--forge-dialog-move-transition-durationThe duration of the move transition.
--forge-dialog-move-transition-easingThe easing function of the move transition.
--forge-dialog-moving-opacityThe opacity of the dialog when it is being moved.
--forge-dialog-enter-animation-durationThe duration of the enter animation.
--forge-dialog-enter-animation-easingThe easing function of the enter animation.
--forge-dialog-exit-animation-durationThe duration of the exit animation.
--forge-dialog-exit-animation-easingThe easing function of the exit animation.
--forge-dialog-zoom-opacityThe opacity of the dialog during zoom animation.
--forge-dialog-zoom-scaleThe scale of the dialog during zoom animation.
--forge-dialog-fade-opacityThe opacity of the dialog during fade animation.
--forge-dialog-slide-opacityThe opacity of the dialog during slide animation.
--forge-dialog-slide-translateThe translation distance of the dialog during slide animation.
--forge-dialog-backdrop-opacityThe opacity of the dialog backdrop.
--forge-dialog-nonmodal-elevationThe elevation of non-modal dialogs.
--forge-dialog-fullscreen-enter-animation-durationThe duration of the enter animation for fullscreen dialogs.
--forge-dialog-fullscreen-exit-animation-durationThe duration of the exit animation for fullscreen dialogs.
--forge-dialog-position-xThe x-axis position of the dialog.
--forge-dialog-position-yThe y-axis position of the dialog.
--forge-dialog-preset-sheet-enter-animation-durationThe duration of the enter animation for preset sheet dialogs.
--forge-dialog-preset-sheet-exit-animation-durationThe duration of the exit animation for preset sheet dialogs.
Methods
NameReturnsDescription
show()voidShows the dialog.
hide()voidHides the dialog.

Labeling

You can’t set aria-labelledby or aria-describedby directly on <forge-dialog> — the native <dialog> element underneath it lives across a shadow boundary those attributes can’t reach. Use labelledby and describedby instead: the id (or space-separated ids) of elements inside the dialog that label or describe it, such as the title in its header toolbar. The dialog resolves them across the shadow boundary, wires up the equivalent ARIA relationships, and announces them correctly when it opens. Note there’s no aria- prefix.

<forge-dialog labelledby="dialog-title" describedby="dialog-message">
  <h2 id="dialog-title" class="forge-typography--heading3">Delete file?</h2>
  <p id="dialog-message">This can't be undone.</p>
</forge-dialog>

labelledby and describedby were added in Forge 3.24.0. On earlier versions, or for a dialog without a visible title, set label and description to plain-text values instead. When both are set, labelledby and describedby take precedence.

<forge-dialog label="Delete file?" description="This can't be undone.">
  <p>Are you sure you want to delete this file?</p>
</forge-dialog>

Give the close icon button in the header an accessible name with aria-label="Close dialog".

Keyboard interaction

Keyboard navigation needs to behave the way it looks — a modal dialog makes the rest of the page inert, so interactive content outside it shouldn’t be reachable while it’s open. If there’s a mouse-only way to close the dialog, make sure there’s a keyboard equivalent too. When the dialog closes, return focus to a logical element on the page rather than losing it.

Screen reader behavior

The dialog automatically applies role="dialog" and aria-modal="true" for you.

Loading Forge chat…