Modals disable underlying content and are used to present a short-term task the user needs to perform without losing the context of the underlying page. Users won't be able to interact with the page until they close the modal. By design, clicking outside the DtModal dialog does not close it — this is intentional behavior to prevent accidental dismissal of important tasks. Users must explicitly click the close button or trigger a close action to dismiss the modal.
Although highly versatile, this doesn't mean modal dialogs are fit for all purposes. Modals are purposefully disruptive and should be used thoughtfully and sparingly, specifically in moments where focus is required or an action must be taken.
a tags must have an hrefattribute. Also, any elements which you don't want to be focusable (but might be focusable by default) must have their tabindex set to -1.aria-labelledby on its root element to associate a title to the modal to announce its to accessible technology. The value of aria-labelledby is to the id value of its heading element (e.g. h2).
Item
|
Applies to
|
Description
|
|---|
<dt-modal header-text="Example title" :open="isOpen" @update:open="updateOpen" copy="Lorem ipsum ..." > <template #footer > <dt-button id="cancel-button" :kind="secondaryButtonKind" importance="clear" > Cancel </dt-button> <dt-button id="confirm-button" importance="primary" > Confirm </dt-button> </template> </dt-modal> <dt-button @click="isOpen = !isOpen" > Click to open </dt-button>
This is the default behavior that adds the scroll automatically in the modal content and leaves the header and footer fixed.
<dt-modal header-text="Example title" :open="isOpen" @update:open="updateOpen" :showFooter="true" :fixed-header-footer="true" copy="Sed at orci quis nunc finibus gravida eget vitae est..." > <template #footer > <dt-button id="cancel-button" :kind="secondaryButtonKind" importance="clear" > Cancel </dt-button> <dt-button id="confirm-button" importance="primary" > Confirm </dt-button> </template> </dt-modal> <dt-button @click="isOpen = !isOpen" > Click to open </dt-button>
A modal style for destructive or irreversible actions.
<dt-modal header-text="Example title" :open="isOpen" kind="critical" copy="Sed at orci quis nunc finibus gravida eget vitae est..." @update:open="updateOpen" > <template #footer > <dt-button id="cancel-button" :kind="secondaryButtonKind" importance="clear" > Cancel </dt-button> <dt-button id="confirm-button" kind="critical" importance="primary" > Confirm </dt-button> </template> </dt-modal> <dt-button @click="isOpen = !isOpen" > Click to open </dt-button>
To make this modal take up as much of the screen as possible.
<dt-modal header-text="Example title" :open="isOpen" fullscreen copy="Sed at orci quis nunc finibus gravida eget vitae est..." @update:open="updateOpen" > <template #footer > <dt-button id="cancel-button" :kind="secondaryButtonKind" importance="clear" > Cancel </dt-button> <dt-button id="confirm-button" importance="primary" > Confirm </dt-button> </template> </dt-modal> <dt-button @click="isOpen = !isOpen" > Click to open </dt-button>
By default, modals render a dimming overlay behind the dialog box. Set transparent-backdrop to render the surrounding backdrop fully transparent. The dialog box itself keeps its solid background. Use this when the underlying UI should remain visible behind the modal.
<dt-modal header-text="Example title" :open="isOpen" transparent-backdrop copy="Sed at orci quis nunc finibus gravida eget vitae est..." @update:open="updateOpen" > <template #footer > <dt-button id="cancel-button" :kind="secondaryButtonKind" importance="clear" > Cancel </dt-button> <dt-button id="confirm-button" importance="primary" > Confirm </dt-button> </template> </dt-modal> <dt-button @click="isOpen = !isOpen" > Click to open </dt-button>
When there is a need of more context information regarding the content of the Modal
<dt-modal header-text="Example title" :open="isOpen" banner-header-text="This banner can have different kinds." :bannerKind="selectedBannerKind" copy="Sed at orci quis nunc finibus gravida eget vitae est..." @update:open="updateOpen" > <template #footer > <dt-button id="cancel-button" :kind="secondaryButtonKind" importance="clear" > Cancel </dt-button> <dt-button id="confirm-button" importance="primary" > Confirm </dt-button> </template> </dt-modal> <dt-button @click="isOpen = !isOpen" > Click to open </dt-button>
You're not limited to using plain title and copy text.
In addition to the footer, custom elements can be inserted into the header and body sections of the dialog via slots.
Please note: supplied header or body slots will take the place of any provided "title" or "copy" text, respectively.
<dt-modal :open="isOpen" @update:open="updateOpen" > <template #header> <dt-stack direction="row" align="center" justify="center" class="d-p-150 d-bgc-purple-100"> <div>Custom header</div> </dt-stack> </template> <dt-stack direction="row" align="center" justify="center" class="d-p-400 d-bgc-gold-200"> <h2>Custom content</h2> </dt-stack> </dt-modal>
Modal content renders outside the DOM tree. Use the contentMode prop to apply color mode (invert, light, dark) to the positioned content. See Positioned Components for details.
<dt-modal content-mode="invert">...</dt-modal> <dt-modal content-mode="dark">...</dt-modal> <dt-modal content-mode="light">...</dt-modal>
import { DtModal } from '@dialpad/dialtone-vue';
Name
|
Type
|
|---|---|
banner | Slot for the banner, defaults to bannerHeaderText prop |
default | Default slot for dialog body section, taking the place of any "copy" text prop |
footer | Slot for dialog footer content, often containing cancel and confirm buttons. |
header | Slot for dialog header section, taking the place of any "headerText" text prop |
Name
|
Default
|
Type
|
|---|---|---|
appendTo | string A CSS selector string for the element to portal the modal to. If not provided, the modal will be rendered in its default location. | |
bannerClass | '' | string|object|array Additional class name for the banner element within the modal.
Can accept String, Object, and Array, i.e. has the
same API as Vue's built-in handling of the class attribute. |
bannerHeaderText | string Header text to display in the modal banner. | |
bannerKind | 'warning' |
"base"
|
"critical"
|
"info"
|
"positive"
|
"warning"
Sets the color of the banner. |
closeOnClick | true |
"true"
|
"false"
Whether the modal will close when you click outside of the dialog on the overlay. |
contentClass | '' | string|object|array Additional class name for the content element within the modal.
Can accept String, Object, and Array, i.e. has the
same API as Vue's built-in handling of the class attribute. |
contentMode |
"light"
|
"dark"
|
"invert"
Applies a color mode to the positioned content element.
| |
copy | '' | string Body text to display as the modal's main content. |
describedById | '' | string Id to use for the dialog's aria-describedby.
Recommended only if the dialog content itself isn't enough to give full context,
as screen readers should recite the dialog contents by default before any aria-description. |
dialogClass | '' | string|object|array Additional class name for the dialog element within the modal.
Can accept String, Object, and Array, i.e. has the
same API as Vue's built-in handling of the class attribute. |
fixedHeaderFooter | true |
"true"
|
"false"
Scrollable modal that allows scroll the modal content keeping the header and footer fixed |
footerClass | '' | string|object|array Additional class name for the footer element within the modal.
Can accept String, Object, and Array, i.e. has the
same API as Vue's built-in handling of the class attribute. |
fullscreen | false |
"true"
|
"false"
Whether the modal fills the viewport instead of rendering at its default size. |
headerClass | '' | string|object|array Additional class name for the header element within the modal.
Can accept String, Object, and Array, i.e. has the
same API as Vue's built-in handling of the class attribute. |
headerText | string Header text to display in the modal header. | |
initialFocusElement | 'first' | string|HTML_ELEMENT_TYPE The element that is focused when the modal is opened. This can be an
HTMLElement within the modal, a string starting with '#' which will
find the element by ID. 'first' which will automatically focus
the first element, or 'dialog' which will focus the dialog window itself.
If the dialog is modal this prop cannot be 'none'. |
kind | 'default' |
"default"
|
"critical"
The theme of the modal. |
labelledById | generated unique ID | string Id to use for the dialog's aria-labelledby. |
modal | false |
"true"
|
"false"
When true, the dialog opens with showModal(), which promotes it to the browser
top layer. Nothing outside the top layer can paint above it regardless of
z-index, so application surfaces such as toasts and call notifications end up
behind it. When false, it opens with show() and stays in the normal stacking
order, where the Dialtone z-index scale applies and --zi-notification (700)
outranks --zi-modal (600) as documented. Focus trapping, scroll locking and Esc-to-close behave identically in both
modes. Background inertness does not: only the top layer provides it, so with
modal unset the page outside the dialog stays reachable. That is deliberate —
it is what lets an application's own overlays remain usable above a modal —
and keyboard containment still comes from the focus trap. |
modalClass | '' | string|object|array Additional class name for the root modal element.
Can accept String, Object, and Array, i.e. has the
same API as Vue's built-in handling of the class attribute. |
open | false |
"true"
|
"false"
Whether the modal should be shown.
Parent component can sync on this value to control the modal's visibility. |
showClose | true |
"true"
|
"false"
Shows the close button on the modal |
transparentBackdrop | false |
"true"
|
"false"
When true, the surrounding backdrop is rendered fully transparent
instead of the default dimming overlay. The dialog box itself
remains opaque. Useful when the underlying UI should remain visible. |
Name
|
Type
|
|---|---|
click | PointerEvent | KeyboardEvent Native button click event |
keydown | KeyboardEvent Native keydown event |
update:open | Boolean The modal will emit a "false" boolean value for this event when the user performs a modal-closing action.
Parent components can sync on this value to create a 2-way binding to control modal visibility. |
At minimum, modals contain a title and one button. They could also contain body text, brand illustrations, product wireframes, or multiple buttons.
Class
|
Applies to
|
Description
|
|---|
Modal documentation last updated Friday, September 4, 2026
fix/popover-modal-zindex-scope