---
title: "文字提示"
description: "Tooltip 在悬停或键盘聚焦时为控件命名或补充一句纯文本提示，支持快捷键展示、触摸开合与多触发器共享。"
---

> Documentation Index
> Fetch the complete documentation index at: https://ui-sdk.ndjp.net/llms.txt
> Use this file to discover all available pages before exploring further.

# 文字提示

`Tooltip`（文字提示）在指针停留或键盘聚焦到达时，为控件命名或补充一句简短提示，保持几个词的纯文本即可。需要交互的内容用[弹出框](https://ui-sdk.ndjp.net/docs/components/popover)，链接目标的预览用[悬停卡片](https://ui-sdk.ndjp.net/docs/components/hover-card)。

## 演示

悬停或用 Tab 聚焦「B」「I」按钮，提示显示名称与快捷键；在同一工具栏内移动时，提示即时跟随而不重复等待延迟。

## 组合

```text
Tooltip
├── TooltipTrigger
└── TooltipContent
    ├── TooltipArrow
    └── TooltipShortcut
```

箭头与快捷键可选。内容具有 `tooltip` 角色，从一开始就隐藏在页面中，因此焦点到达前就能为触发器命名或描述：没有自身名称的触发器（如纯图标按钮）被命名，其余被描述，`type="label"` / `type="description"` 可覆盖这个判断。提示不可聚焦，里面放链接或按钮无法到达，交互内容请改用弹出框或悬停卡片。

## 用法

```tsx
import { Tooltip, TooltipContent, TooltipTrigger } from "@ui-sdk/react/tooltip";

function Example() {
  return (
    <Tooltip>
      <TooltipTrigger>分享</TooltipTrigger>
      <TooltipContent>任何拥有链接的人都可以查看</TooltipContent>
    </Tooltip>
  );
}
```

## 快捷键提示

根部件的 `shortcut`（如 `"mod+s"`）只是提示触发器动作绑定的按键，`mod` 在 Apple 平台是 Command，其余是 Control。`TooltipShortcut` 按平台显示 `⌘S` 或 `Ctrl+S`，对屏幕阅读器隐藏；触发器获得 `aria-keyshortcuts` 让读屏用户听到。它也可以用自己的 `shortcut` 显示其他按键。

提示本身不绑定按键：用 `@ui-sdk/core/shortcuts` 的 `registerShortcut` 自行注册，或使用会绑定按键的组件（如[对话框](https://ui-sdk.ndjp.net/docs/components/dialog)触发器的 `shortcut`）。

```tsx
<Tooltip shortcut="mod+s">
  <TooltipTrigger aria-label="保存">
    <SaveIcon aria-hidden="true" />
  </TooltipTrigger>
  <TooltipContent>
    保存
    <TooltipShortcut />
  </TooltipContent>
</Tooltip>
```

## 触摸与按下行为

触摸屏没有悬停，点按普通提示的触发器只会执行按钮本身，提示保持关闭，所以不要把重要信息藏进提示。只为提示而存在的信息按钮加 `toggleable`：按下即开合，手指、鼠标、键盘都有效，按下打开时播报文本，外部点击或 Escape 也能关闭。

按下触发器默认关闭提示（`closeOnPress`），以免盖住按下后变化的内容，并在指针离开前保持关闭；设为 `false` 可保持打开，例如提示变成「已复制」的复制按钮。原生 `disabled` 按钮无法聚焦、部分浏览器不派发指针事件，提示永远不显示：要解释原因为何不可用时，改用 `aria-disabled="true"` 并自行忽略按下，按钮恢复可用后用提示的 `disabled` 关掉解释。

```tsx
<Tooltip toggleable>
  <TooltipTrigger aria-label="关于存储空间">
    <InfoIcon aria-hidden="true" />
  </TooltipTrigger>
  <TooltipContent>回收站中的文件仍占用空间。</TooltipContent>
</Tooltip>
```

## 延迟与分组

`delay` 是指针停留多久后打开，默认 600 毫秒；`closeDelay` 是指针离开触发器与提示后多久关闭，默认 0；键盘聚焦立即打开。提示无需 provider 自动分组：一个打开着或刚关闭不久时，悬停下一个立即打开，且同一时刻只有一个打开，沿工具栏移动就像一条跟着指针的提示；立即打开的提示带 `data-instant`，可跳过动画。`disabled` 阻止打开，触发器照常工作。

```tsx
<Tooltip delay={300} closeDelay={150} disabled={!showHints}>
```

## 多触发器共享一个提示

工具栏、图表或长列表可以共享一条提示：把触发器与提示连到同一个 `createTooltipController<Payload>()`，触发器可以在页面任何位置，各自传 `payload`，内容从 `state.payload` 读取（首次打开前就会渲染，要处理 `undefined`）。只有打开提示的触发器被它描述，所以每个触发器要有自己的名称（如 `aria-label`）。`controller.open({ payload, anchor })` 可从代码打开（例如引导教程的一步），`onPayloadChange` 报告每次载荷变化。

```tsx
const tip = createTooltipController<string>();

<TooltipTrigger controller={tip} payload="加粗" aria-label="加粗">
  <BoldIcon aria-hidden="true" />
</TooltipTrigger>

<Tooltip controller={tip}>
  <TooltipContent<string>>{(state) => state.payload}</TooltipContent>
</Tooltip>
```

## 样式与状态

内容默认在触发器上方（`side="top"`），空间不足时翻转并平移保持可见；`sideOffset` 默认 4px，`align`、`alignOffset`、`collisionPadding`、`arrowPadding` 与 `anchor`（元素、选择器、`{ x, y }` 点）和弹出框一致。`TooltipArrow` 跟随实际落点一侧。

`data-slot` 为 `tooltip-content` 与 `tooltip-arrow`，带 `data-open` / `data-closed`、`data-side` / `data-align`，内容另有 `data-starting-style` / `data-ending-style` 与 `data-instant`；触发器与 Shortcut 没有状态属性，因为触发器常兼任其他组件的触发器。CSS 变量：`--anchor-width` / `--anchor-height`、`--available-width` / `--available-height`、`--transform-origin`、`--arrow-offset`。

```css
[data-slot="tooltip-content"] {
  transform-origin: var(--transform-origin);
  transition: opacity 150ms ease-out, scale 150ms ease-out;
}
[data-slot="tooltip-content"]:is([data-starting-style], [data-ending-style]) {
  opacity: 0;
  scale: 0.9;
}
[data-slot="tooltip-content"][data-instant] {
  transition: none;
}
```

提示就地渲染进浏览器顶层，不会被祖先裁剪或遮盖，`container` 可移动 DOM；退场播完才卸载，`onOpenChangeComplete` 在动画结束后触发。详见[弹出层](https://ui-sdk.ndjp.net/docs/concepts/popups)。

## API

| Prop | 类型 | 说明 |
| --- | --- | --- |
| `open` / `defaultOpen` | `boolean` | 受控 / 非受控的开合状态。 |
| `onOpenChange` | `(open, details) => void` | 开合变更；`details.reason` 如 `trigger-hover`、`trigger-focus`、`escape-key`，可 `cancel()`。 |
| `onOpenChangeComplete` | `(open: boolean) => void` | 动画结束后报告开合完成。 |
| `onPayloadChange` | `(payload, details) => void` | 共享提示的载荷变化，可 `cancel()`。 |
| `delay` / `closeDelay` | `number` | 打开 / 关闭前的停顿，默认 600ms / 0ms。 |
| `disabled` | `boolean` | 不打开提示，触发器照常工作。 |
| `toggleable` | `boolean` | 按下触发器开合提示，供触摸与信息按钮使用。 |
| `closeOnPress` | `boolean` | 按下触发器是否关闭提示，默认 `true`。 |
| `type` | `"label" \| "description"` | 覆盖命名 / 描述的自动判断。 |
| `shortcut` | `string` | 快捷键提示，不绑定按键。 |
| `controller` | `PopupController` | 用 `createTooltipController()` 创建，连接外部触发器。 |
| `container` | `Element \| DocumentFragment \| null` | 渲染到指定元素而非就地。 |

`TooltipContent` 另有 `side`、`align`、`sideOffset`、`alignOffset`、`collisionPadding`、`arrowPadding`、`anchor`、`container`；`TooltipTrigger` 有 `payload` 与 `controller`；`TooltipShortcut` 有 `shortcut`。

## 键盘与无障碍

触发器由提示命名或描述，遵循 WAI-ARIA tooltip 模式；悬停与键盘聚焦都会打开，指针移到提示上不会关闭。

| 按键 | 行为 |
| --- | --- |
| `Tab` | 聚焦触发器立即打开；焦点离开即关闭 |
| `Escape` | 关闭提示，焦点留在触发器，不关闭外层的对话框或菜单 |
| `Enter` / `Space` | 按下触发器并关闭提示；`toggleable` 时开合提示 |

提示内容不可聚焦，也不应包含交互元素。只在文本被截断时显示提示，可在 `onOpenChange` 里比较 `scrollWidth` 与 `clientWidth`，放得下就 `details.cancel()`，并用 `type="label"` 避免读屏重复朗读。

## 相关组件

- [弹出框](https://ui-sdk.ndjp.net/docs/components/popover)：点击打开、可交互的内容。
- [悬停卡片](https://ui-sdk.ndjp.net/docs/components/hover-card)：链接目标的丰富预览。
- [弹出层](https://ui-sdk.ndjp.net/docs/concepts/popups)：顶层渲染与定位变量的共享模型。
- [控制器](https://ui-sdk.ndjp.net/docs/concepts/controllers)：多触发器共享一条提示的连接方式。

Source: https://ui-sdk.ndjp.net/docs/components/tooltip/index.mdx
