MessageBox
Introduction
MMessageBox is a modal dialog component designed for important notifications or scenarios requiring explicit user confirmation. It offers alert and confirm modes, six built-in semantic types, and programmatic invocation via useMessageBox().
Usage
Place the trigger element in the default slot. The component internally manages the open state via UModal:
<template>
<MMessageBox title="Save Changes" description="Click "Got it" to close the dialog.">
<UButton label="Open" />
</MMessageBox>
</template>
mode Mode
alert shows only a confirm button; confirm provides both cancel and confirm buttons, returning a boolean result:
<template>
<MMessageBox mode="confirm">
<UButton label="Open" color="neutral" variant="subtle" />
</MMessageBox>
</template>
type Type
type affects the default icon and confirm button color, with six semantic values:
<template>
<MMessageBox type="primary" mode="confirm">
<UButton label="Open" color="neutral" variant="subtle" />
</MMessageBox>
</template>
icon Icon
icon overrides the default icon from type. Pass any Iconify icon name:
<template>
<MMessageBox icon="i-lucide-rocket">
<UButton variant="soft" color="success" label="Deployment Complete" />
</MMessageBox>
</template>
label Button Labels
alertConfirmLabel controls the alert mode button label. confirmLabel and cancelLabel override the two buttons in confirm mode respectively:
<template>
<MMessageBox
mode="confirm"
alert-confirm-label="Acknowledged"
confirm-label="I Agree"
cancel-label="I Disagree"
>
<UButton variant="outline" label="Custom Labels" />
</MMessageBox>
</template>
buttonProps Button Properties
confirmButton and cancelButton accept full ButtonProps, allowing customization of icon, color, variant, and label:
<template>
<MMessageBox
:confirm-button="{ label: 'Continue', icon: 'i-lucide-arrow-right', color: 'info' }"
:cancel-button="{ label: 'Cancel', variant: 'ghost' }"
>
<UButton variant="outline" label="Button Properties" />
</MMessageBox>
</template>
dismissible Close Strategy
dismissible defaults to false (strict mode). When enabled, clicking the overlay or pressing Esc closes the dialog and marks it as unconfirmed via close(false):
<template>
<MMessageBox dismissible>
<UButton variant="outline" color="neutral" label="Close Strategy" />
</MMessageBox>
</template>
Examples
Controlled State
Use v-model:open to control the open state externally — ideal for programmatic triggering and multi-button coordination:
<script setup lang="ts">
const open = ref(false)
const result = ref('')
</script>
<template>
<div class="flex gap-2">
<UButton variant="soft" @click="open = true">
外部按钮打开
</UButton>
<UButton color="neutral" variant="outline" @click="open = false">
外部按钮关闭
</UButton>
<span v-if="result" class="self-center text-sm text-muted">{{ result }}</span>
<MMessageBox
v-model:open="open"
mode="confirm"
type="primary"
title="确认执行同步"
:dismissible="false"
:modal="false"
description="open 由父组件持有,可被任意按钮、定时器或异步任务触发。"
@close="(ok: boolean) => result = `受控 → ${ok}`"
/>
</div>
</template>
Body Slot
The body slot renders rich text content. The close slot parameter allows programmatically closing the dialog from within the body:
<template>
<MMessageBox
mode="confirm"
type="primary"
title="服务条款更新"
>
<UButton color="primary" variant="soft" icon="i-lucide-file-text" label="阅读条款" />
<template #body="{ close }">
<p class="text-sm text-muted">
我们对服务条款进行了以下更新,请仔细阅读:
</p>
<ul class="mt-2 space-y-1 text-sm list-disc list-inside text-muted">
<li>数据收集范围已缩减</li>
<li>用户隐私保护条款已加强</li>
<li>退款政策已更新</li>
</ul>
<UButton
class="mt-3"
size="xs"
variant="ghost"
color="neutral"
label="先取消,稍后阅读"
@click="close"
/>
</template>
</MMessageBox>
</template>
Title Slot
The title slot fully takes over the title area, replacing the default icon-plus-text combination:
<template>
<MMessageBox
mode="confirm"
type="primary"
title="原标题文案"
description="标题区由 #title 插槽决定,原 title prop 不会渲染。"
>
<UButton variant="outline" label="自定义标题" />
<template #title>
<UIcon name="i-lucide-sparkles" class="size-5 text-primary" />
<span class="font-bold text-primary">完全自定义的标题样式</span>
<UBadge color="primary" variant="subtle" label="NEW" />
</template>
</MMessageBox>
</template>
Description Slot
The description slot supports rich text descriptions and works alongside the title prop:
<template>
<MMessageBox
mode="alert"
type="info"
title="版本更新说明"
>
<UButton variant="outline" label="查看说明" />
<template #description>
<span class="text-sm">
v2.0 已发布,详见
<a href="#" class="text-primary underline">完整变更日志</a>
,或继续使用旧版。
</span>
</template>
</MMessageBox>
</template>
Header Slot
The header slot fully takes over the title and description container, enabling custom layout and typography:
<template>
<MMessageBox
mode="confirm"
type="warning"
title="原标题"
description="原描述"
>
<UButton variant="outline" label="自定义头部" />
<template #header>
<div class="flex items-center gap-3 p-4 bg-warning/10 rounded-t-lg">
<UIcon name="i-lucide-triangle-alert" class="size-8 text-warning" />
<div>
<div class="font-semibold">
高风险操作
</div>
<div class="text-xs text-muted">
头部插槽自定义整块布局
</div>
</div>
</div>
</template>
</MMessageBox>
</template>
Footer Slot
The footer slot fully takes over the button area. The close slot parameter is used to close the dialog:
<template>
<MMessageBox
mode="confirm"
type="primary"
title="步进式确认"
description="footer 插槽接管按钮区,可自由组合多按钮、分组、状态等。"
>
<UButton variant="outline" label="自定义操作" />
<template #footer="{ close }">
<UButton color="neutral" variant="ghost" label="稍后处理" @click="close" />
<UButton color="warning" variant="soft" label="保留并继续" @click="close" />
<UButton color="primary" label="立即应用" @click="close" />
</template>
</MMessageBox>
</template>
Close Button Slot
The close slot customizes the top-right close button — change icon, color, and styles:
<template>
<MMessageBox
mode="alert"
type="info"
title="自定义关闭按钮"
description="close 插槽完全替换默认关闭按钮。"
>
<UButton variant="outline" label="查看" />
<template #close>
<UButton size="xs" color="error" variant="ghost" icon="i-lucide-x-circle" />
</template>
</MMessageBox>
</template>
Content Slot
The content slot replaces the entire header / body / footer layout — ideal for fully custom scenarios:
<template>
<MMessageBox title="原标题">
<UButton variant="soft" color="primary" label="极致定制" />
<template #content="{ close }">
<div class="p-6 flex flex-col items-center gap-4 text-center">
<UIcon name="i-lucide-party-popper" class="size-12 text-primary" />
<div class="text-lg font-semibold">
恭喜达成成就
</div>
<p class="text-sm text-muted">
content 插槽替代 header/body/footer 三段式,可完全自定义内部结构。
</p>
<UButton label="收下奖励" @click="close" />
</div>
</template>
</MMessageBox>
</template>
Programmatic Usage
Use useMessageBox() to invoke dialogs from any logic without declaring the component in templates. alert() returns Promise<void>, and confirm() returns Promise<boolean>:
<script setup lang="ts">
const { alert, confirm } = useMessageBox()
const alertResult = ref('')
const confirmResult = ref('')
async function showAlert() {
await alert({
type: 'success',
title: '操作成功',
description: '数据已成功提交,await 会等待弹窗关闭后继续执行。'
})
alertResult.value = 'await 后的逻辑已执行'
}
async function showConfirm() {
const ok = await confirm({
type: 'error',
title: '清空数据',
description: '即将清空所有本地缓存,此操作不可撤销。',
icon: 'i-lucide-database-zap',
confirmButton: { color: 'error', label: '确认清空' },
cancelButton: { label: '我再想想' }
})
confirmResult.value = ok ? '数据已清空' : '操作已取消'
}
</script>
<template>
<div class="space-y-3">
<div class="flex flex-wrap gap-3">
<div class="flex items-center gap-3">
<UButton
color="success"
variant="soft"
label="alert()"
icon="i-lucide-bell"
@click="showAlert"
/>
<span v-if="alertResult" class="text-sm text-muted">{{ alertResult }}</span>
</div>
<div class="flex items-center gap-3">
<UButton
color="error"
variant="outline"
label="confirm()"
icon="i-lucide-database-zap"
@click="showConfirm"
/>
<span v-if="confirmResult" class="text-sm text-muted">{{ confirmResult }}</span>
</div>
</div>
</div>
</template>
API
Props
| Prop | Default | Type |
|---|---|---|
title | '提示' | string模态框标题文本。 |
type | 'primary' | "primary" | "info" | "success" | "warning" | "error" | "neutral"控制消息框的语义类型。 会影响默认图标与确认按钮颜色。 |
mode | 'alert' | "alert" | "confirm"控制消息框的操作模式。
|
alertConfirmLabel | '知道了' | stringalert 模式下的确认按钮文本。 |
confirmLabel | '确认' | string确认按钮文本。 |
cancelLabel | '取消' | string取消按钮文本。 |
description | string | |
content | DialogContentProps & Partial<EmitsToProps<DialogContentImplEmits>>The content of the modal. | |
portal | true | string | false | true | HTMLElementRender the modal in a portal. |
close | true | boolean | Omit<ButtonProps, LinkPropsKeys>Display a close button to dismiss the modal.
|
closeIcon | appConfig.ui.icons.close | anyThe icon displayed in the close button. |
icon | 'i-lucide-circle-question-mark' | any标题前展示的图标名称。 |
confirmButton | ButtonProps透传给确认按钮的属性。
未显式指定 | |
cancelButton | ButtonProps透传给取消按钮的属性。
仅在 | |
open | boolean | |
dismissible | false | boolean当 |
overlay | true | booleanRender an overlay behind the modal. |
scrollable | false | booleanWhen |
transition | true | booleanAnimate the modal when opening or closing. |
fullscreen | false | booleanWhen |
modal | booleanThe modality of the dialog When set to | |
ui | Record<string, SlotClass> & { overlay?: SlotClass; content?: SlotClass; header?: SlotClass; wrapper?: SlotClass; body?: SlotClass; footer?: SlotClass; title?: SlotClass; description?: SlotClass; close?: SlotClass; icon?: SlotClass; } |
Emits
| Event | Type |
|---|---|
close | [confirmed: boolean] |
update:open | [value: boolean] |
Slots
| Slot | Type |
|---|---|
default | { open: boolean; } |
content | { close: () => void; } |
header | { close: () => void; } |
title | {} |
description | {} |
actions | {} |
close | { ui: { overlay: (props?: Record<string, any>) => string; content: (props?: Record<string, any>) => string; header: (props?: Record<string, any>) => string; wrapper: (props?: Record<string, any>) => string; body: (props?: Record<string, any>) => string; footer: (props?: Record<string, any>) => string; title: (props?: Record<string, any>) => string; description: (props?: Record<string, any>) => string; close: (props?: Record<string, any>) => string; }; } |
body | { close: () => void; } |
footer | { close: () => void; } |
Theme
export default defineAppConfig({
ui: {
messageBox: {
slots: {
title: 'flex gap-2 items-center',
footer: 'justify-end',
icon: 'size-5 shrink-0'
},
variants: {
type: {
primary: {
icon: 'text-primary'
},
info: {
icon: 'text-info'
},
success: {
icon: 'text-success'
},
warning: {
icon: 'text-warning'
},
error: {
icon: 'text-error'
},
neutral: {
icon: 'text-muted'
}
}
}
}
}
})