Dialog
The Dialog component is a flexible and extensible content container overlay on either the primary window or another dialog. It is based on the HTML <dialog> element and can be used to create both modal and non-modal dialog boxes. Modal dialog boxes interrupt interaction with the rest of the page being inert, while non-modal dialog boxes allow interaction with the rest of the page. Inert content outside an active dialog box is usually visually obscured or dimmed, making it difficult to discern. By default, modal overlays contain their own tab sequence, preventing users from navigating outside the component. The component implements the W3C ARIA APG Dialog (Modal) Pattern as well as the W3C ARIA APG Alert and Message Dialogs Pattern.
Examples
Base
As dialogs are generally placed as an overlay on top of the rest of the page content, every dialog needs a mechanism that allows users to close it. The most reliable way is to include an explicit button for this purpose, such as a Confirm, Cancel or Close button. The component itself can handle different types of user actions that can be used to close the dialog box.
The main closeable property will add a close button to the dialog header. The closeOnBackdrop property adds a a light dismiss user action, which closes the dialog box when the user clicks or taps outside of it. The closeOnEscape property allows platform-specific user actions, such as pressing the ESC key on desktop platforms, or performing a "back" or "dismiss" gesture on mobile platforms, to close the dialog box. Furthermore, by setting the cancelButton or confirmButton properties, associated buttons will be rendered in the footer section. With closeOnConfirm, the confirm button can also be used to close the dialog.
Show code
<section>
<o-button
label="Open Dialog"
size="medium"
variant="primary"
:aria-expanded="isActive"
aria-controls="base-dialog"
@click="isActive = true" />
<o-dialog
id="base-dialog"
v-model:active="isActive"
closeable
:backdrop="false">
<template #title>Dialog Title</template>
<template #subtitle>Dialog Subtitle</template>
<template #content>
<div>
<p style="text-align: center">
<img
alt="Oruga logo"
src="https://avatars2.githubusercontent.com/u/66300512?s=200&v=4" />
</p>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Etiam sodales leo nec convallis rutrum. Vivamus pharetra
molestie arcu at dictum. Nulla faucibus leo eget enim
egestas, in tempus justo venenatis. Duis dictum suscipit
erat, a dapibus eros lobortis ac. Praesent tempor
rhoncus convallis. Nullam in ipsum convallis, rutrum
elit eget, dictum ipsum. Nunc sagittis aliquet massa.
Etiam lacus sapien, eleifend non eros quis, finibus
ornare nisl. Ut laoreet sit amet lacus non dignissim.
Sed convallis mattis enim, sed interdum risus molestie
ut. Praesent vel ex hendrerit, cursus lectus a, blandit
felis. Nam luctus orci nec varius commodo.
</p>
</div>
</template>
<template #footer="{ close }">
<o-button label="Close" @click="close" />
</template>
</o-dialog>
</section>
import { ref } from "vue";
const isActive = ref(false);
Modal
A simple modal dialog box is created by setting the backdrop property, which inert the background. By default, attempting to interact with the backdrop closes the dialog box.
Setting the blockScroll property removes the body scrollbar. However, the body retains a non-scrollable scrollbar to prevent the background from shifting. This will set the body to position="fixed", which may cause some layouts to break.
Show code
<section>
<o-button
label="Open Modal Dialog"
size="medium"
variant="primary"
:aria-expanded="isActive"
aria-controls="modal-dialog"
@click="isActive = true" />
<o-dialog
id="modal-dialog"
v-model:active="isActive"
backdrop
:loading="isLoading"
:title="title"
:subtitle="subtitle"
:content="content"
closeable />
</section>
import { ref } from "vue";
const isActive = ref(false);
const isLoading = ref(false);
const title = "Dialog Title";
const subtitle = "Dialog Subtitle";
const content = `
Lorem ipsum dolor sit amet, consectetur adipisicing elit.
Inventore sed consequuntur error repudiandae numquam
deserunt quisquam repellat libero asperiores earum nam nobis,
culpa ratione quam perferendis esse, cupiditate neque quas!`;
Alert
An alert dialog box is a type of modal dialog that interrupts the user's workflow in order to communicate an important message and to acquire a response. It is defined by setting the alert property. Examples include action confirmation prompts and error message confirmations. The dialog will have the ARIA: alertdialog role , enabling assistive technologies and browsers to distinguish it from other dialogs and giving them the option to treat it specially, e.g. by playing a system alert sound.
Show code
<section>
<o-button
label="Open Alert Dialog"
size="medium"
variant="primary"
:aria-expanded="isActive"
aria-controls="alert-dialog"
@click="isActive = true" />
<o-dialog
id="alert-dialog"
v-model:active="isActive"
alert
title="Delete Dialog"
content="Are you sure you want to delete this?"
text-position="center"
button-position="center"
cancel-button="Cancel"
confirm-button="Delete"
confirm-variant="danger"
close-on-confirm />
</section>
import { ref } from "vue";
const isActive = ref(false);
Form
One useful purpose of a dialog is to display forms within it. Each slot provides the close() and confirm()functions, which can be called from inside the slot content to trigger component events. Using the autofocus attribute to explicitly indicate the initial focus placement will help ensure the focus is initially set on the focusable element deemed to be the best initial focus placement for any particular dialog.
Show code
<o-button
label="Open Form Dialog"
size="medium"
variant="primary"
@click="isActive = true" />
<o-dialog
v-slot="{ close, confirm }"
v-model:active="isActive"
:backdrop="false"
title="Login"
closeable
@close="onClose"
@confirm="onLogin">
<form method="dialog">
<o-field label="Email">
<o-input
type="email"
autofocus
placeholder="Your email"
required />
</o-field>
<o-field label="Password">
<o-input
type="password"
password-reveal
placeholder="Your password"
required />
</o-field>
<o-field>
<o-checkbox label="Remember me" />
</o-field>
<div style="display: flex; align-items: center; gap: 5px">
<o-button type="button" label="Close" @click="close" />
<o-button label="Login" variant="primary" @click="confirm" />
</div>
</form>
</o-dialog>
import { ref } from "vue";
const isActive = ref(false);
function onClose(): void {
alert("close");
}
function onLogin(): void {
alert("login");
}
Fullscreen
Using the fullscreen property, the dialog will cover the entire user viewport.
Show code
<section>
<o-button
label="Open Fullscreen Dialog"
size="medium"
variant="primary"
@click="isActive = true" />
<o-dialog
v-model:active="isActive"
closeable
fullscreen
title="Dialog Title"
subtitle="Dialog Subtitle"
cancel-button="Close">
<div>
<p style="text-align: center">
<img
alt="Oruga logo"
src="https://avatars2.githubusercontent.com/u/66300512?s=200&v=4" />
</p>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Etiam sodales leo nec convallis rutrum. Vivamus pharetra
molestie arcu at dictum. Nulla faucibus leo eget enim
egestas, in tempus justo venenatis. Duis dictum suscipit
erat, a dapibus eros lobortis ac. Praesent tempor rhoncus
convallis. Nullam in ipsum convallis, rutrum elit eget,
dictum ipsum. Nunc sagittis aliquet massa. Etiam lacus
sapien, eleifend non eros quis, finibus ornare nisl. Ut
laoreet sit amet lacus non dignissim. Sed convallis mattis
enim, sed interdum risus molestie ut. Praesent vel ex
hendrerit, cursus lectus a, blandit felis. Nam luctus orci
nec varius commodo.
</p>
</div>
</o-dialog>
</section>
import { ref } from "vue";
const isActive = ref(false);
Image
The component provides a separate image section in the body where an image can be placed using the imageSrc property. For accessibility reasons, don't forget to add an imageAlt property too.
Show code
<section>
<o-button
label="Open Image Dialog"
size="medium"
variant="primary"
@click="isActive = true" />
<o-dialog
v-model:active="isActive"
image-alt="Oruga Logo"
image-src="https://avatars2.githubusercontent.com/u/66300512?s=200&v=4" />
</section>
import { ref } from "vue";
const isActive = ref(false);
Position
You can quickly change the alignment of all the text in the dialog box using the textPosition property. Additionally, you can align the footer buttons independently using the buttonPosition property.
Show code
<section>
<o-button
label="Open Position Dialog"
size="medium"
variant="primary"
@click="isActive = true" />
<o-dialog
v-model:active="isActive"
close-on-confirm
title="Dialog Title"
subtitle="Dialog Subtitle"
content="Lorem ipsum dolor sit amet, consectetur adipisicing elit. Inventore sed consequuntur error repudiandae numquam deserunt quisquam repellat libero asperiores earum nam nobis, culpa ratione quam perferendis esse, cupiditate neque quas!"
text-position="center"
cancel-button="Cancel"
confirm-button="Confirm"
button-position="right" />
</section>
import { ref } from "vue";
const isActive = ref(false);
Templates
The dialog container is seperated into a header, body and footer section, which can be defined separately either through properties or template slots. Therefore, the component provides a header, title, subtitle, content, footer as well as confirmButton and cancelButton named template slots, which can be used to customise HTML content.
Show code
<section>
<o-button
label="Open Dialog"
size="medium"
variant="primary"
@click="isActive = true" />
<o-dialog v-model:active="isActive" closeable>
<template #title>Advanced Dialog</template>
<template #subtitle>Dialog subtitle</template>
<template #image>
<img
alt="Oruga Logo"
src="https://avatars2.githubusercontent.com/u/66300512?s=200&v=4" />
</template>
<template #content>
<p class="m-0">
Lorem ipsum dolor sit amet, consectetur adipisicing elit.
Inventore sed consequuntur error repudiandae numquam
deserunt quisquam repellat libero asperiores earum nam
nobis, culpa ratione quam perferendis esse, cupiditate neque
quas!
</p>
</template>
<template #cancelButton>
<a href="#" class="dialog-link">A link</a>
</template>
<template #confirmButton>
<a href="#" class="dialog-link">Another link</a>
</template>
</o-dialog>
</section>
import { ref } from "vue";
const isActive = ref(false);
Dynamic Component
Rather than using the default slot, the component prop allows to pass any component that will be programmatically rendered inside the dialog component. Furthermore, an inline component created with a render function can also be passed. Props and events can be passed to the component with props and events properties too.
Show code
<section class="odocs-spaced">
<o-button
label="Open component modal"
size="medium"
variant="primary"
@click="isActive = true" />
<o-dialog
v-model:active="isActive"
title="Advanced Dialog"
image-alt="Oruga Logo"
image-src="https://avatars2.githubusercontent.com/u/66300512?s=200&v=4"
:component="myComponent"
cancel-button="Finish" />
</section>
import { h, ref } from "vue";
const isActive = ref(false);
const myComponent = h("div", [
"Some quick example text to build on the dialog title and make up the bulk of the dialog's content.",
]);
Teleport
The teleport prop allows the dialog to be "teleported" into any DOM node outside the DOM hierarchy of the component placed in. By default, if only a boolean is passed, the diaog will be teleported to the document body. In addition, any other destination could be passed as string or the DOM Node element.
Show code
<section>
<o-button
label="Open Teleported Dialog"
size="medium"
variant="primary"
@click="isActive = true" />
<o-dialog v-model:active="isActive" teleport backdrop close-on-backdrop>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam
sodales leo nec convallis rutrum. Vivamus pharetra molestie arcu
at dictum. Nulla faucibus leo eget enim egestas, in tempus justo
venenatis. Duis dictum suscipit erat, a dapibus eros lobortis
ac. Praesent tempor rhoncus convallis. Nullam in ipsum
convallis, rutrum elit eget, dictum ipsum. Nunc sagittis aliquet
massa. Etiam lacus sapien, eleifend non eros quis, finibus
ornare nisl. Ut laoreet sit amet lacus non dignissim. Sed
convallis mattis enim, sed interdum risus molestie ut. Praesent
vel ex hendrerit, cursus lectus a, blandit felis. Nam luctus
orci nec varius commodo.
</p>
</o-dialog>
</section>
import { ref } from "vue";
const isActive = ref(false);
Programmatically
This component provides a programmatic interface that can be accessed by the useOruga() composable. The composable can be used from outside of the Vue instance. For example, it can be used in Pinia or Vue Router with this syntax:
import { useOruga } from "@oruga-ui/oruga-next";
const oruga = useOruga();
oruga.dialog.open({...});
Show code
<section class="odocs-spaced">
<p>
<o-button
label="Open Confirm Dialog"
size="medium"
variant="primary"
@click="openConfirmDialog()" />
<o-button
label="Open Oruga Image"
size="medium"
variant="primary"
@click="openImageDialog()" />
</p>
</section>
import { h } from "vue";
import { useOruga } from "@oruga-ui/oruga-next";
const oruga = useOruga();
function openConfirmDialog(): void {
oruga.dialog.open({
title: "Save Dialog",
content: "Are you sure you want to save this?",
confirmButton: "Save",
confirmVariant: "success",
cancelButton: "Cancel",
buttonPosition: "right",
});
}
function openImageDialog(): void {
// here we use a render function to create an dynamic inline component (https://vuejs.org/guide/extras/render-function)
const vnode = h("p", { style: { "text-align": "center" } }, [
"This is the Oruga Logo!",
]);
oruga.dialog.open({
component: vnode,
closeOnBackdrop: true,
closeOnEscape: true,
imageAlt: "Oruga logo",
imageSrc: "https://avatars2.githubusercontent.com/u/66300512?s=200&v=4",
});
}
A programmatic instance returns a promise to await for. The promise gets resolved when the dialog gets closed.
Show code
<section class="odocs-spaced">
<p>
<o-button
label="Open Prompt Dialog"
size="medium"
variant="primary"
@click.prevent="promptDialog()" />
<o-button
label="Open Prompt Dialog (with timeout)"
size="medium"
variant="primary"
@click.prevent="promptTimeoutDialog()" />
</p>
</section>
import { useOruga } from "@oruga-ui/oruga-next";
const oruga = useOruga();
const promptDialog = async (): Promise<void> => {
const instance = oruga.dialog.open({
backdrop: true,
title: "Ship sprockets?",
content: "Do you really want me to ship the selected sprockets?",
cancelButton: "No",
confirmButton: "Yes",
confirmVariant: "primary",
closeOnConfirm: true,
});
// wait until the dialog got closed
await instance.promise;
oruga.notification.open({
duration: 5000,
message: "Dialog closed",
variant: "info",
position: "top",
closeable: true,
});
};
const promptTimeoutDialog = async (): Promise<void> => {
const instance = oruga.dialog.open({
backdrop: true,
closeable: true,
title: "Closed By Timeout",
content:
"There is a 3 second timeout that will close this programmatic dialog.",
});
// close the last opened dialog in 3 seconds
setTimeout(() => oruga.dialog.close(), 3000);
// wait until the dialog got closed
await instance.promise;
oruga.notification.open({
duration: 5000,
message: "Dialog closed",
variant: "info",
position: "top",
closeable: true,
});
};
Dialog Component
Dialog is a container to display content in an overlay window.
<o-dialog></o-dialog>Props
| Prop name | Description | Type | Values | Default |
|---|---|---|---|---|
| active | Whether dialog is active or not, use v-model:active to make it two-way binding | boolean | - | false |
| alert | This enables the alertdialog role, allowing assistive technologies and browsers to distinguish alert dialogs from other dialogs.Alert dialogs interrupt the user's workflow to communicate an important messages and acquire an explicit response. Examples include error messages that require confirmation and other action confirmation prompts. | boolean | - | |
| animation | Custom animation (transition name) | string | - | From config: dialog: { |
| ariaCloseLabel | Accessibility label for the close button | string | - | From config: dialog: { |
| ariaDescribedby | Accessibility aria-describedby to be passed to the div root element - if a title is set, it is linked to the title | string | - | |
| ariaLabel | Accessibility aria-label to be passed to the div root element | string | - | |
| backdrop | Show an backdrop overlay background; make it a modal dialog | boolean | - | From config: dialog: { |
| blockScroll | Whether background scrollbar should be blocked/removed when dialog is visible | boolean | - | From config: dialog: { |
| buttonPosition | Position of the footer buttons | "center" | "left" | "right" | - | |
| cancelButton | Render a cancel button and set text text as label | string | - | |
| cancelVariant | Color variant of the cancel button | string | primary, info, success, warning, danger, and any other custom color | |
| closeIcon | Close icon name | string | - | From config: dialog: { |
| closeIconSize | Close icon size | string | - | From config: dialog: { |
| closeOnBackdrop | Close the dialog when clicked outside of the panel | boolean | - | From config: dialog: { |
| closeOnConfirm | Close the dialog when the confirm button is preset | boolean | - | From config: dialog: { |
| closeOnEscape | Close the dialog when pressing escape key | boolean | - | From config: dialog: { |
| closeable | Adds close button to the header to hide the dialog | boolean | - | From config: dialog: { |
| component | Component to be injected. Close the component by emitting a 'close' event — $emit('close') | C | - | |
| confirmButton | Render a confirm button and set text as label | string | - | |
| confirmVariant | Color variant of the confirm button | string | primary, info, success, warning, danger, and any other custom color | |
| content | Dialog body content, unnecessary when content slot is used | string | - | |
| disableCancel | Disable the cancel button | boolean | - | |
| disableConfirm | Disable the confirm button | boolean | - | |
| events | Events to be binded to the injected component | EmitsToProps<ComponentEmit<C>> | - | |
| fullscreen | Display dialog as full screen | boolean | - | false |
| iconPack | Icon pack to use for the close icon | string | mdi, fa, fas and any other custom icon pack | From config: dialog: { |
| imageAlt | Dialog image alt, unnecessary when image slot is used | string | - | |
| imageSrc | Dialog image src, unnecessary when image slot is used | string | - | |
| loading | Show a loading spinner in the dialog | boolean | - | |
| loadingLabel | Show label beside the loading icon | string | - | |
| maxHeight | Max height of the dialog | Numberish | - | From config: dialog: { |
| maxWidth | Max width of the dialog | Numberish | - | From config: dialog: { |
| mobileBreakpoint | Mobile breakpoint as max-width value | string | - | From config: dialog: { |
| override | Override existing theme classes completely | boolean | - | |
| props | Props to be binded to the injected component | ComponentProps<C> | - | |
| subtitle | Dialog header subtitle, unnecessary when subtitle slot is used | string | - | |
| teleport | Append the component to another part of the DOM. Set true to append the component to the body.In addition, any CSS selector string or an actual DOM node can be used. | boolean | object | string | - | From config: dialog: { |
| textPosition | Text alignment in its entirely | "center" | "left" | "right" | - | |
| title | Dialog header title, unnecessary when title slot is used | string | - |
Events
| Event name | Properties | Description |
|---|---|---|
| update:active | value boolean - updated active prop | active prop two-way binding |
| close | event Event - native event | the event is fired when the dialog has been closed |
| cancel | event Event - native event | the event is fired when the user wish to dismiss the current open dialog |
| confirm | event Event - native event | the event is fired when the confirm button get clicked |
Slots
| Name | Description | Bindings |
|---|---|---|
| header | Override the header | close (event: Event): void - function to emit a close event |
| title | Override the header title, default is title prop | |
| subtitle | Override the header subtitle, default is subtitle prop | |
| close | Define a custom close icon | |
| image | Override the image element | |
| default | Override the default dialog body | close (event: Event): void - function to emit a close eventconfirm (event: Event): void - function to emit a confirm event |
| content | Override the body content, default is content prop | close (event: Event): void - function to emit a close eventconfirm (event: Event): void - function to emit a confirm event |
| footer | Override the footer | close (event: Event): void - function to emit a close eventconfirm (event: Event): void - function to emit a confirm event |
| cancelButton | Define the cancel button label | |
| confirmButton | Define the confirm button label |
Class Inspector
| Class prop | Description | Props | Suffixes | |
|---|---|---|---|---|
| rootClass | Class of the root element. | |||
| mobileClass | Class of the root element when on mobile. 👉 Switch to mobile view to see it in action! | |||
| activeClass | Class of the root element when active. | active | ||
| fullscreenClass | Class of the root element when fullscreen. | fullscreen | ||
| teleportClass | Class of the root element when teleported. | teleport | ||
| textPositionClass | Class of the root element with text position. | textPosition | left | |
| backdropClass | Class of the backdrop overlay element. | backdrop | ||
| wrapperClass | Class of the wrapper element. | |||
| headerClass | Class of the header element. | |||
| titleClass | Class of the header title element. | |||
| subtitleClass | Class of the header subtitle element. | |||
| closeClass | Class of the header close element. | |||
| figureClass | Class of the image figure element. | |||
| imageClass | Class of the image element. | |||
| bodyClass | Class of the body element. | |||
| contentClass | Class of the body content element. | |||
| footerClass | Class of the footer element. | |||
| footerPositionClass | Class of the footer element with position. | buttonPosition | left | |
| confirmButtunClass | Class of the footer confirm button element. | confirmButton | ||
| cancelButtonClass | Class of the footer cancel button element. | cancelButton | ||
| scrollClipClass | Class of the body when dialog is active and has blockScroll. | blockScroll | ||
| scrollKeepClass | Class of the body when dialog is active and has not blockScroll. | blockScroll |
Sass Variables
Current theme ➜ Oruga
| SASS Variable | Default |
|---|---|
| $dialog-spacer | calc(2 * h.useVar("control-spacer")) |
| $dialog-zindex | map.get(vars.$zindex, "fixed") |
| $dialog-box-shadow | h.useVar("overlay-box-shadow") |
| $dialog-background-color | h.useVar("control-brackground-color") |
| $dialog-border-width | h.useVar("control-border-width") |
| $dialog-border-style | solid |
| $dialog-border-color | h.useVar("control-border-color") |
| $dialog-border-radius | h.useVar("border-radius") |
| $dialog-backdrop-background-color | h.useVar( "overlay-background-color") |
| $dialog-header-padding | $dialog-spacer |
| $dialog-header-background-color | inherit |
| $dialog-body-padding | $dialog-spacer |
| $dialog-body-background-color | inherit |
| $dialog-footer-padding | $dialog-spacer |
| $dialog-footer-background-color | inherit |
| $dialog-title-color | h.useVar("font-color") |
| $dialog-title-font-size | 2em |
| $dialog-title-font-weight | bold |
| $dialog-subtitle-color | h.useVar("font-color") |
| $dialog-subtitle-font-size | 1.5em |
| $dialog-subtitle-font-weight | normal |
| $dialog-content-color | h.useVar("font-color") |
| $dialog-content-font-size | h.useVar("font-size") |
| $dialog-content-font-weight | h.useVar("font-weight") |
| $dialog-close-top | $dialog-spacer |
| $dialog-close-right | $dialog-spacer |
| $dialog-close-color | h.useVar("black") |
| $dialog-close-size | 2rem |
| $dialog-close-border-radius | h.useVar("border-radius-rounded") |
| $dialog-close-background-color | inherit |
See ➜ 📄 SCSS file
Current theme ➜ Bulma
The theme does not have any custom variables for this component.
