# Tooltip 文字提示

给一个元素补充一句解释，不占布局。气泡挂在 `body` 上用 `position: fixed` 定位，因此不会被父级 `overflow` 裁剪；主轴空间不足时会自动翻到对侧。

## 代码演示

### 基础用法

`content` 传纯文本，或用 `#content` 插槽写结构化内容。默认 hover 触发、延迟 300ms。

```vue
<template>
  <div class="m-row-demo">
    <MTooltip content="默认 hover 触发，300ms 后出现" placement="top">
      <MButton variant="outlined" color="primary">悬停查看</MButton>
    </MTooltip>
    <MTooltip placement="bottom">
      <template #content>
        自定义内容
        <br />
        支持多行与任意结构
      </template>
      <MButton variant="text" color="primary">插槽内容</MButton>
    </MTooltip>
  </div>
</template>
```

### 方位

`placement` 支持四个主轴方向与四组带对齐的方位，共 12 种取值。靠近视口边缘时组件会自动翻转成对侧。

**演示说明：** 逐个悬停可以对照入场位移与对齐方式。

```vue
<script setup lang="ts">
const placements = [
  'top',
  'bottom',
  'left',
  'right',
  'top-start',
  'top-end',
  'bottom-start',
  'bottom-end',
  'left-start',
  'left-end',
  'right-start',
  'right-end',
] as const
</script>

<template>
  <div class="m-row-demo m-demo-stage">
    <MTooltip
      v-for="placement in placements"
      :key="placement"
      :placement="placement"
      :content="placement">
      <MButton variant="text" color="secondary" size="small">{{ placement }}</MButton>
    </MTooltip>
  </div>
</template>
```

### 触发方式

`hover` 适合补充说明，`click` 适合需要停留阅读的内容，`focus` 只靠键盘与焦点也能触达。

**演示说明：** click 模式下点击气泡外任意处会关闭。

```vue
<template>
  <div class="m-row-demo m-demo-stage">
    <MTooltip trigger="hover" content="hover 触发：进入后延迟 300ms 出现，移出立即消失">
      <MButton variant="outlined" color="primary">hover</MButton>
    </MTooltip>
    <MTooltip trigger="click" content="click 触发：点击切换，点击外部关闭">
      <MButton variant="outlined" color="primary">click</MButton>
    </MTooltip>
    <MTooltip trigger="focus" content="focus 触发：获得焦点显示，失焦关闭">
      <MButton variant="outlined" color="primary">focus</MButton>
    </MTooltip>
  </div>
</template>
```

### 自定义内容

`#content` 插槽优先于 `content` 属性。

```vue
<template>
  <div class="m-row-demo m-demo-stage">
    <MTooltip placement="bottom" :open-delay="0">
      <template #content>
        <strong>自定义内容</strong>
        <div>插槽里可以放标题、列表或任意节点。</div>
      </template>
      <MButton variant="outlined" color="secondary">#content 插槽</MButton>
    </MTooltip>
    <MTooltip placement="right" content="纯文本提示，用 content 属性最省事">
      <MButton variant="outlined" color="secondary">content 属性</MButton>
    </MTooltip>
  </div>
</template>
```

### 延迟与禁用

`openDelay` / `closeDelay` 只对 `hover` 生效；`disabled` 置为 `true` 时正在显示的气泡会立即关闭。

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

const disabled = ref(false)
</script>

<template>
  <div class="m-row-demo m-demo-stage">
    <MTooltip content="无延迟，进入即显示" :open-delay="0">
      <MButton variant="tonal" color="info">openDelay 0</MButton>
    </MTooltip>
    <MTooltip content="关闭延迟 600ms，移出后还会停留一会儿" :close-delay="600">
      <MButton variant="tonal" color="info">closeDelay 600</MButton>
    </MTooltip>
    <MTooltip content="这段提示已被禁用" :disabled="disabled">
      <MButton variant="tonal" color="info">disabled</MButton>
    </MTooltip>
    <MSwitch v-model="disabled" color="primary">禁用提示</MSwitch>
  </div>
</template>
```

## API

### Props

| 属性 | 类型 | 默认值 | 说明 |
| --- | --- | --- | --- |
| `content` | `string` | `undefined` | 提示内容；也可用 `#content` 插槽 |
| `placement` | `TooltipPlacement` | `'top'` | 弹出方向，空间不足时自动翻转并按视口夹紧 |
| `trigger` | `'hover' \| 'click' \| 'focus'` | `'hover'` | 触发方式 |
| `disabled` | `boolean` | `false` | 是否禁用；置为 `true` 时立即关闭 |
| `openDelay` | `number` | `300` | 显示延迟（ms），仅 `hover` 生效 |
| `closeDelay` | `number` | `0` | 关闭延迟（ms），仅 `hover` 生效 |
| `modelValue` | `boolean` | `undefined` | 受控显示状态（`v-model`） |
| `appendToBody` | `boolean` | `true` | 挂载到 `body`，避免被父级 `overflow` 裁剪 |

### Events

| 事件 | 参数 | 说明 |
| --- | --- | --- |
| `update:modelValue` | `value: boolean` | 受控显示状态变化 |
| `open` | 无 | 气泡显示 |
| `close` | 无 | 气泡隐藏 |

### Slots

| 插槽 | 参数 | 说明 |
| --- | --- | --- |
| `default` | 无 | 触发区内容 |
| `content` | 无 | 自定义提示内容；无内容时回退到 `content` 属性 |

### 类型定义

```ts
export type TooltipSide = 'top' | 'bottom' | 'left' | 'right';
export type TooltipPlacement =
  | TooltipSide
  | 'top-start' | 'top-end'
  | 'bottom-start' | 'bottom-end'
  | 'left-start' | 'left-end'
  | 'right-start' | 'right-end';
export type TooltipTrigger = 'hover' | 'click' | 'focus';
```

## 使用建议

::: tip 鼠标可以从触发区移到气泡上
气泡本身也监听 `hover`：鼠标进入气泡会取消关闭计时。因此可以让提示内容足够长、允许用户把鼠标移进去选中文字。
:::

::: tip 位置是算出来的，不是纯 CSS
组件读取触发区与气泡的实际尺寸，先按 `placement` 算基准位置，主轴空间不足时翻到对侧，最后把坐标夹紧在视口内。滚动与窗口尺寸变化时会重新计算。
:::

::: warning `openDelay` / `closeDelay` 只对 hover 有效
`click` 与 `focus` 触发的显示、隐藏是即时的，设置延迟不会生效。
:::

::: warning 气泡没有箭头
`MTooltip` 的气泡是一条纯色圆角矩形，内部没有指向触发区的三角箭头，方向完全由位置表达。
:::

## 相关组件

- [Dropdown 下拉菜单](/components/dropdown)：需要承载可交互内容的浮层。
- [Icon 图标](/components/icon)：给纯图标元素配 Tooltip 补足语义。
