# Alert 警告提示

把一条需要被看见、但不需要用户操作的消息固定在页面流里。与 `MToast` 的区别是：Alert 占据布局位置、常驻展示；Toast 悬浮在角落、自动消失。

## 代码演示

### 基础用法

`severity` 决定语义与配色，`title` 是加粗的标题行，正文放在默认插槽。

**演示说明：** 点关闭按钮会触发 `close` 事件并弹出提示。

```vue
<script setup lang="ts">
import { toast } from 'miao-design'

function onClose() {
  toast.info('close 已触发，组件自身不会复位')
}
</script>

<template>
  <MAlert severity="success" title="保存成功" closable @close="onClose">
    数据已同步到服务器。
  </MAlert>
</template>
```

### 四种严重级别

`success` / `info` / `warning` / `error` 各自对应一套图标与配色。

```vue
<template>
  <div class="m-row-demo--stretch">
    <MAlert severity="success" title="成功">
      配置已发布到生产环境。
    </MAlert>
    <MAlert severity="info" title="提示">
      本次变更为灰度发布，覆盖 10% 流量。
    </MAlert>
    <MAlert severity="warning" title="警告">
      磁盘使用率已达 85%，请及时清理。
    </MAlert>
    <MAlert severity="error" title="错误">
      数据库连接超时，请检查网络与白名单。
    </MAlert>
  </div>
</template>
```

### 三种外观变体

`standard` 浅底、`filled` 实底、`outlined` 描边。变体只改外观，语义色仍由 `severity` 决定。

```vue
<script setup lang="ts">
const variants = [
  { value: 'standard', label: 'standard 浅底' },
  { value: 'filled', label: 'filled 实底' },
  { value: 'outlined', label: 'outlined 描边' },
] as const
</script>

<template>
  <div class="m-row-demo--stretch">
    <MAlert
      v-for="item in variants"
      :key="item.value"
      :variant="item.value"
      severity="warning"
      :title="item.label">
      variant 只改外观，语义色仍然由 severity 决定。
    </MAlert>
  </div>
</template>
```

### 图标控制

`showIcon` 控制内置语义图标；一旦传入 `#icon` 插槽，内置图标会被替换掉。

```vue
<script setup lang="ts">
import { mdiBellRingOutline } from '@mdi/js'
</script>

<template>
  <div class="m-row-demo--stretch">
    <MAlert severity="info" title="默认图标">
      `showIcon` 默认是 `true`，显示内置的语义图标。
    </MAlert>
    <MAlert severity="info" :show-icon="false" title="隐藏图标">
      `showIcon` 设为 `false` 后左侧不再留出图标位置。
    </MAlert>
    <MAlert severity="success" title="自定义图标">
      <template #icon>
        <MIcon :path="mdiBellRingOutline" :size="20" />
      </template>
      传了 `#icon` 插槽后内置图标自动隐藏，此时 `showIcon` 不再起作用。
    </MAlert>
  </div>
</template>
```

### 标题

标题可以来自 `title` 属性，也可以用 `#title` 插槽写富文本；两者同时存在时插槽优先。

```vue
<template>
  <div class="m-row-demo--stretch">
    <MAlert severity="info" title="通过 title 属性">
      正文放在默认插槽里。
    </MAlert>
    <MAlert severity="warning">
      <template #title>通过 #title 插槽 <strong>（支持富文本）</strong></template>
      `#title` 插槽优先于 `title` 属性。
    </MAlert>
    <MAlert severity="error">
      只有正文、没有标题时不会渲染标题行。
    </MAlert>
  </div>
</template>
```

### 关闭与重新挂载

关闭是组件内部状态。点关闭后组件自己动画离场并保持消失，需要重新显示必须由外部换 `key` 或重新挂载。

```vue
<script setup lang="ts">
import { ref } from 'vue'
import { toast } from 'miao-design'

const mountKey = ref(0)

function remount() {
  mountKey.value += 1
}

function onClose() {
  toast.warning('已关闭；换 key 才能再次显示')
}
</script>

<template>
  <div class="m-row-demo--stretch">
    <MAlert
      :key="mountKey"
      severity="warning"
      title="可关闭提示"
      closable
      @close="onClose">
      点击右上角关闭后，组件内部会置 `closed = true` 并播放离场动画，但不会自己复位。
    </MAlert>
    <div class="m-row-demo">
      <MButton variant="outlined" color="warning" size="small" @click="remount">
        换 key 重新挂载
      </MButton>
    </div>
  </div>
</template>
```

## API

### Props

| 属性 | 类型 | 默认值 | 说明 |
| --- | --- | --- | --- |
| `severity` | `'success' \| 'info' \| 'warning' \| 'error'` | `'info'` | 语义类型，决定图标与配色 |
| `variant` | `'standard' \| 'filled' \| 'outlined'` | `'standard'` | 外观变体：浅底 / 实底 / 描边 |
| `closable` | `boolean` | `false` | 显示右上角关闭按钮，点击后进入离场动画 |
| `showIcon` | `boolean` | `true` | 是否显示内置语义图标；传入 `#icon` 插槽时内置图标自动隐藏 |
| `title` | `string` | `undefined` | 标题文本；也可用 `#title` 插槽 |

### Events

| 事件 | 参数 | 说明 |
| --- | --- | --- |
| `close` | 无 | 点击关闭按钮时触发，同时组件内部置 `closed = true` 开始离场动画 |

### Slots

| 插槽 | 参数 | 说明 |
| --- | --- | --- |
| `default` | 无 | 提示正文 |
| `icon` | 无 | 自定义图标；提供后自动隐藏内置语义图标 |
| `title` | 无 | 自定义标题；无内容时回退到 `title` 属性 |

## 使用建议

::: tip 只有正文时不会渲染标题行
`title` 属性为空且没有 `#title` 插槽内容时，标题行整行不渲染。同理，默认插槽为空时正文行也不渲染，所以「只有标题」的 Alert 是合法写法。
:::

::: warning 关闭后组件不会自行复位
关闭动作只改组件内部的 `closed` 状态：动画播完后内容从 DOM 移除，`closable` 的图标也跟着消失。想再次展示必须由消费方干预，通常是给组件换一个 `key` 或用 `v-if` 重新挂载。

```vue
<MAlert v-if="visible" closable @close="visible = false">...</MAlert>
```

注意 `v-if` 与 `@close` 绑同一个开关时，组件会在同一帧被卸载，离场动画会被打断；`close` 后先置内部状态、再由用户操作重新显示的写法（例如换 `key`）才能看到完整的离场动画。
:::

::: warning `showIcon` 对 `#icon` 插槽无效
内置图标的渲染条件是 `showIcon && !$slots.icon`。只要传了 `#icon`，内置图标就会隐藏，此时把 `showIcon` 设成 `false` 也不会影响你自定义的那个图标。
:::

## 相关组件

- [Toast 轻提示](/components/toast)：非阻塞的临时消息，自动消失，不占布局。
- [Dialog 对话框](/components/dialog)：需要用户确认后再继续的场景。
