Dialog
A Dialog is a container that is overlaid on a web page or app in order to present necessary information and tasks. A Dialog is sometimes referred to as a modal or an overlay.
| Name | Value |
|---|---|
| Props | |
title | |
subtitle | |
hideTitle | |
useCloseButton | |
stackedActions | |
usePrimaryAction | |
primaryActionLabel | |
primaryActionType | |
primaryActionDisabled | |
useDefaultAction | |
defaultActionLabel | |
defaultActionDisabled | |
| Slots | |
default | |
footer-text | |
| View | |
Reading direction | |
Overview
When to use Dialog
Dialogs facilitate communication between the system and user. They perform best when used for urgent decisions or as a workflow within a bigger task, as they don’t require loading a new page and keep actions in context.
Dialogs are intentionally disruptive, since the user needs to interact with or close the Dialog before moving on. For this reason, they should be used sparingly and only when necessary.
Use the Dialog component when:
- The user needs to make a decision or provide input to the system before continuing with the task at hand.
- Additional information needs to be displayed and separated from the page content.
- The user needs to provide additional confirmation before taking an action.
Avoid using Dialog when:
- The information can be displayed within the main interface.
- The information is not important enough to interrupt the user's flow.
- The content is long or complex, like a form with numerous fields, and cannot be split into multiple steps within a Dialog.
About Dialog
Dialog includes the following elements.
Header
The Dialog header must contain a title, though it can be visually-hidden if the Dialog's purpose is clear from context. A subtitle can be used to provide additional information about the Dialog.
A quiet, icon-only Button may be used to close the Dialog. It can also be replaced with a text Button in some cases.
Body
Any type of content or components can be included within the Dialog’s body.
- Avoid using Cards or other elevated components within the Dialog.
Footer
One to two action buttons should appear at the end of the Dialog. A primary Button (either progressive or destructive) is used to indicate the main action. A normal neutral Button can be used to indicate a default action (e.g. “Cancel”).
- Include at least one action button.
- Stack action buttons based on text length when needed, placing the primary button on top.
- Don't stack action buttons when they can be placed side by side.
The Dialog footer can include text above the action buttons to provide additional information (e.g. terms and conditions to read before publishing).
A permanent action can be included (e.g. a "Don't show again" checkbox) (refer to the Multi-step Dialog for an example).
Examples
Basic usage
This example includes a title, close button, footer text, primary action, and default action.
<client-only> tag
The examples on this page are all wrapped with VitePress's built-in <client-only> component, since the Codex documentation site (built with VitePress) uses SSR. Other SSRed applications will need to do something similar (only rendering Dialog after the mounted hook has been fired, etc.).
This tag has been removed from the MediaWiki examples, as <client-only> is meaningless there.
With form inputs
A Dialog can be used to gather user input. For long forms with many inputs, consider splitting the Dialog into multiple steps or creating a separate page instead.
Stacked actions
The action buttons in the footer are stacked vertically on narrow screens, but appear side by side on wide screens. In some situations, like when the button text is long, you can force the action buttons to always be stacked vertically regardless of screen size.
Developer notes
When using the default Dialog footer, use the stackedActions prop to force the action buttons to be stacked vertically, even on wide screens.
Custom header and footer
By default, the Dialog displays a header with a title and optional subtitle and close button, and a footer with optional buttons and footer text.
The entire contents of the header and footer can be replaced with custom content, layout, and styles. You could:
- Use a text button in place of the icon-only close button in the header.
- Use icon-only action buttons in the footer (such as previous and next buttons in a multi-step Dialog).
- Add a permanent action in the footer (such as a "Don't show again" checkbox), which should appear next to the buttons (or above them them, in the case of stacked actions).
- Ensure the primary action button remains in the footer and place it after the default action, if there is one.
- When stacking action buttons, ensure they are full-width.
- Always use a quiet Button for the close button of the Dialog.
Developer notes
Override the default header and footer via the header and footer slots.
Multi-step Dialog
You can make a multi-step Dialog by customizing the header and footer and showing different content in the body section.
This example is based on the Growth Team's Add a Link Dialog.
Technical implementation
Vue usage
The parent component controls whether the Dialog is open via v-model:open.
A Dialog can offer two kinds of actions (represented by buttons of the appropriate type): primary action (can be progressive or destructive), and default action (typically a safe option like "cancel").
When open, the Dialog adds a class to the document body to prevent scrolling; this is applied whether or not teleport is used.
Attributes passed to inner element
This component forwards any attributes applied by the user to the inner .cdx-dialog element, instead of applying them to the outermost backdrop element.
Dialog and <teleport>
Dialogs rely on Vue's built-in <teleport> feature. By default, Dialogs will be teleported to the <body> element on the page, but this can be changed using Vue's provide/inject feature, with provide( 'CdxTeleportTarget', '#my-teleport-target' ). If Dialog is being used with SSR, a dedicated teleport target should be provided.
Dialog teleportation can be disabled by setting the renderInPlace prop.
Styling content in teleported Dialogs
When a Dialog is teleported (which is the default unless the renderInPlace prop is set), its contents will not be descendants of the element that contains the <cdx-dialog> tag. When styling the contents of a Dialog, be careful not to use CSS selectors that assume the Dialog is inside its parent component.
For example, CSS selectors like .my-component .cdx-dialog or .my-component .something-inside-the-dialog won't work. Instead, set e.g. class="my-component-dialog" on the <cdx-dialog> tag, and use that class to style the dialog and things inside it.
Props
| Prop name | Description | Type | Default |
|---|---|---|---|
open | Whether the dialog is visible. Should be provided via a v-model:open binding in the parent scope. | boolean | false |
title(required) | Title for the dialog header. Used for ARIA purposes even if no visible header element is displayed. | string | |
subtitle | Optional subtitle for the dialog. | string | null |
hideTitle | Whether the dialog header should hide the title & subtitle | boolean | false |
useCloseButton | Add an icon-only close button to the dialog header. On narrow screens, the close button is always displayed. On wide screens, it's only displayed if this prop is set. | boolean | false |
closeButtonLabel | Visually-hidden label text for the icon-only close button in the header. Omit this prop to use the default value, "Close". | string | '' |
primaryAction | Primary user action. This will display a primary button with the specified action (progressive or destructive). | PrimaryModalAction | null |
defaultAction | Default user action. This will display a normal button. | ModalAction | null |
stackedActions | Whether action buttons should be vertically stacked and 100% width. | boolean | false |
target | Selector or DOM element identifying the container the dialog should be rendered in. The dialog will be <teleport>ed to this element. An ID selector is recommended, e.g. #foo-bar, but providing an actual element is also supported.If this prop is not set, and the parent or one of its ancestors provides a teleport target using provide( 'CdxTeleportTarget', '#foo-bar' ), the provided target will be used. If there is no provided target, the dialog will be teleported to the end of the <body> element. | string|HTMLElement|null | null |
renderInPlace | Whether to disable the use of teleport and render the Dialog in its original location in the document. If this is true, the target prop is ignored. | boolean | false |
Events
| Event name | Properties | Description |
|---|---|---|
primary | When the primary action button is clicked. | |
default | When the default action button is clicked. | |
update:open | newValue boolean - The new open/close state (true for open, false for closed) | When the open/close state changes, e.g. when the close button is clicked. |
Slots
| Name | Description | Bindings |
|---|---|---|
| header | Customizable Dialog header | |
| default | Dialog content | |
| footer | Customizable Dialog footer | |
| footer-text | Optional footer text |
Keyboard navigation
| Key | Function |
|---|---|
| Tab | It moves the focus to the next interactive element in tab order within the Dialog. |
| Shift + Tab | It moves the focus to the previous interactive element within the Dialog. |
| Enter | If the focus is placed on one of the Dialog’s buttons, it activates the button. |
| Esc | It closes the Dialog. |