Examples
Basic
<script setup lang="ts">
const open = ref(false);
</script>
<template>
<UiButton variant="secondary" @click="open = true">Open dialog</UiButton>
<UiDialog v-model:open="open" title="Keyboard shortcuts" description="Work faster with these.">
<ul class="demo-list">
<li>Search <UiKbd keys="mod+k" size="small" /></li>
<li>Save <UiKbd keys="mod+s" size="small" /></li>
<li>Close <UiKbd keys="esc" size="small" /></li>
</ul>
</UiDialog>
</template>
Copy codeThe footer slot gets a close function.
<script setup lang="ts">
const open = ref(false);
const name = ref("Acme Inc.");
const toast = useToast();
function save(close: () => void) {
toast.success(`Renamed to ${name.value}`);
close();
}
</script>
<template>
<UiButton @click="open = true">Rename workspace</UiButton>
<UiDialog v-model:open="open" title="Rename workspace" size="sm">
<UiInput v-model="name" label="Workspace name" autofocus />
<template #footer="{ close }">
<UiButton variant="ghost" @click="close">Cancel</UiButton>
<UiButton @click="save(close)">Save</UiButton>
</template>
</UiDialog>
</template>
Copy codeRequired step
With dismissible off, Escape, the backdrop and the × button do nothing; only your own buttons close it.
<script setup lang="ts">
const open = ref(false);
const accepted = ref(false);
</script>
<template>
<UiButton variant="secondary" @click="open = true">Review terms</UiButton>
<UiDialog
v-model:open="open"
title="We've updated our terms"
description="Accept them to keep using your account."
size="sm"
:dismissible="false"
>
<UiCheckbox v-model="accepted" label="I accept the new terms" />
<template #footer="{ close }">
<UiButton :disabled="!accepted" @click="close">Continue</UiButton>
</template>
</UiDialog>
</template>
Copy codeAPI
| Prop | Type | Default |
|---|
titleHeading, which names the dialog. | string | — |
labelAccessible name when there's no visible title. | string | — |
descriptionSupporting text, announced as the dialog's description. | string | — |
dismissibleWhether Escape, the backdrop and the header's close button can close it. The slots' close always can. | boolean | true |
sizeSize hook, exposed as data-dialog-size. | "lg" | "md" | "sm" | "xl" | "md" |
flushLayout hook for edge-to-edge content, exposed as data-dialog-flush. | boolean | false |
closeOnBackdropClose when the backdrop is clicked. | boolean | true |
showCloseButtonRender the header's close button. | boolean | true |
openWhether the dialog is open. | boolean | false |
| Event | Payload |
|---|
closeClosed by any means. | [] |
update:openv-model:open update.
| [value: boolean] |
| Slot | Props |
|---|
defaultBody content. Mounted on first open. | { close: () => void; } |
headerReplaces the title and description. | — |
footerActions, e.g. buttons. | { close: () => void; } |
close-iconReplaces the close button's icon. | — |
Styling
- Parts
dialogdialog-paneldialog-headerdialog-header-textdialog-titledialog-descriptiondialog-closedialog-bodydialog-footer- States
data-dialog-sizedata-dialog-flush
Keyboard
| Keys | Action |
|---|
Escape | Close (when dismissible) |
Tab | Cycle within the dialog |
Accessibility
- The page behind is inert and doesn't scroll; focus returns to the opener on close.
- Named by
title, or label without one.