---
title: "MessageBox"
description: "A modal message dialog offering both declarative and programmatic usage."
canonical_url: "https://nuxt.mhaibaraai.cn/en/docs/components/message-box"
---
# MessageBox

> A modal message dialog offering both declarative and programmatic usage.

## 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()`.

> [!NOTE]
> See: https://ui.nuxt.com/docs/components/modal
> 
> Built on Nuxt UI's Modal component

## Usage

Place the trigger element in the `default` slot. The component internally manages the open state via `UModal`:

```vue
<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:

```vue
<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:

```vue
<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:

```vue
<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:

```vue
<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:

```vue
<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)`:

```vue
<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:

```vue [ComponentsMessageBoxControlledExample.vue]
<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:

```vue [ComponentsMessageBoxBodySlotExample.vue]
<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:

```vue [ComponentsMessageBoxTitleSlotExample.vue]
<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:

```vue [ComponentsMessageBoxDescriptionSlotExample.vue]
<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:

```vue [ComponentsMessageBoxHeaderSlotExample.vue]
<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:

```vue [ComponentsMessageBoxFooterSlotExample.vue]
<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:

```vue [ComponentsMessageBoxCloseSlotExample.vue]
<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:

```vue [ComponentsMessageBoxContentSlotExample.vue]
<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>`:

```vue [ComponentsMessageBoxProgrammaticExample.vue]
<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

```ts
/**
 * Props for the MMessageBox component
 */
interface MMessageBoxProps {
  /**
   * 模态框标题文本。
   * @default '提示'
   */
  title?: string | undefined;
  /**
   * 控制消息框的语义类型。
   * 会影响默认图标与确认按钮颜色。
   * @default 'primary'
   */
  type?: "error" | "primary" | "info" | "success" | "warning" | "neutral" | undefined;
  /**
   * 标题前展示的图标名称。
   * @default 'i-lucide-circle-question-mark'
   */
  icon?: any;
  /**
   * 控制消息框的操作模式。
   * `alert` 仅显示确认按钮，`confirm` 显示取消与确认按钮。
   * @default 'alert'
   */
  mode?: "alert" | "confirm" | undefined;
  /**
   * 当 `false` 时，点击遮罩层或按下 `Esc` 键将不会关闭模态框。
   * @default false
   */
  dismissible?: boolean | undefined;
  /**
   * alert 模式下的确认按钮文本。
   * @default '知道了'
   */
  alertConfirmLabel?: string | undefined;
  /**
   * 确认按钮文本。
   * @default '确认'
   */
  confirmLabel?: string | undefined;
  /**
   * 取消按钮文本。
   * @default '取消'
   */
  cancelLabel?: string | undefined;
  /**
   * 透传给确认按钮的属性。
   * 未显式指定 `color` 时会默认继承当前 `type`。
   */
  confirmButton?: ButtonProps | undefined;
  /**
   * 透传给取消按钮的属性。
   * 仅在 `mode='confirm'` 时渲染。
   */
  cancelButton?: ButtonProps | undefined;
  ui?: Record<string, SlotClass> & { overlay?: SlotClass; content?: SlotClass; header?: SlotClass; wrapper?: SlotClass; body?: SlotClass; footer?: SlotClass; title?: SlotClass; description?: SlotClass; close?: SlotClass; icon?: SlotClass; } | undefined;
  description?: string | undefined;
  /**
   * The content of the modal.
   */
  content?: Omit<DialogContentProps, "as" | "asChild" | "forceMount"> & Partial<EmitsToProps<DialogContentImplEmits>> | undefined;
  /**
   * Render an overlay behind the modal.
   * @default true
   */
  overlay?: boolean | undefined;
  /**
   * When `true`, enables scrollable overlay mode where content scrolls within the overlay.
   * @default false
   */
  scrollable?: boolean | undefined;
  /**
   * Animate the modal when opening or closing.
   * @default true
   */
  transition?: boolean | undefined;
  /**
   * When `true`, the modal will take up the full screen.
   * @default false
   */
  fullscreen?: boolean | undefined;
  /**
   * Render the modal in a portal.
   * @default true
   */
  portal?: string | false | true | HTMLElement | undefined;
  /**
   * Display a close button to dismiss the modal.
   * `{ size: 'md', color: 'neutral', variant: 'ghost' }`{lang="ts-type"}
   * @default true
   */
  close?: boolean | Omit<ButtonProps, LinkPropsKeys> | undefined;
  /**
   * The icon displayed in the close button.
   * @default appConfig.ui.icons.close
   */
  closeIcon?: any;
  /**
   * The modality of the dialog When set to `true`, <br>
   * interaction with outside elements will be disabled and only dialog content will be visible to screen readers.
   */
  modal?: boolean | undefined;
  /**
   * When set to `false`, the dialog content will not be unmounted when closed, but instead hidden with CSS. <br>
   * Useful for SEO or when you want to improve performance by not remounting the component on every open.
   * @default true
   */
  unmountOnHide?: boolean | undefined;
  open?: boolean | undefined;
}
```

### Emits

```ts
/**
 * Emitted events for the MMessageBox component
 */
interface MMessageBoxEmits {
  close: (payload: [confirmed: boolean]) => void;
  update:open: (payload: [value: boolean | undefined]) => void;
}
```

### Slots

```ts
/**
 * Slots for the MMessageBox component
 */
interface MMessageBoxSlots {
  default(): any;
  content(): any;
  header(): any;
  title(): any;
  description(): any;
  actions(): any;
  close(): any;
  body(): any;
  footer(): any;
}
```

## Theme

<component-theme>



</component-theme>

## Changelog

See commit history for [src/runtime/components/MessageBox.vue](https://github.com/mhaibaraai/movk-nuxt/commits/main/src/runtime/components/MessageBox.vue).


## Sitemap

See the full [sitemap](https://nuxt.mhaibaraai.cn/sitemap.md) for all pages.
