Tooltip(文字提示)在指针停留或键盘聚焦到达时,为控件命名或补充一句简短提示,保持几个词的纯文本即可。需要交互的内容用弹出框,链接目标的预览用悬停卡片。
演示
悬停或用 Tab 聚焦「B」「I」按钮,提示显示名称与快捷键;在同一工具栏内移动时,提示即时跟随而不重复等待延迟。
组合
Tooltip
├── TooltipTrigger
└── TooltipContent
├── TooltipArrow
└── TooltipShortcut箭头与快捷键可选。内容具有 tooltip 角色,从一开始就隐藏在页面中,因此焦点到达前就能为触发器命名或描述:没有自身名称的触发器(如纯图标按钮)被命名,其余被描述,type="label" / type="description" 可覆盖这个判断。提示不可聚焦,里面放链接或按钮无法到达,交互内容请改用弹出框或悬停卡片。
用法
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 自行注册,或使用会绑定按键的组件(如对话框触发器的 shortcut)。
<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 关掉解释。
<Tooltip toggleable>
<TooltipTrigger aria-label="关于存储空间">
<InfoIcon aria-hidden="true" />
</TooltipTrigger>
<TooltipContent>回收站中的文件仍占用空间。</TooltipContent>
</Tooltip>延迟与分组
delay 是指针停留多久后打开,默认 600 毫秒;closeDelay 是指针离开触发器与提示后多久关闭,默认 0;键盘聚焦立即打开。提示无需 provider 自动分组:一个打开着或刚关闭不久时,悬停下一个立即打开,且同一时刻只有一个打开,沿工具栏移动就像一条跟着指针的提示;立即打开的提示带 data-instant,可跳过动画。disabled 阻止打开,触发器照常工作。
<Tooltip delay={300} closeDelay={150} disabled={!showHints}>多触发器共享一个提示
工具栏、图表或长列表可以共享一条提示:把触发器与提示连到同一个 createTooltipController<Payload>(),触发器可以在页面任何位置,各自传 payload,内容从 state.payload 读取(首次打开前就会渲染,要处理 undefined)。只有打开提示的触发器被它描述,所以每个触发器要有自己的名称(如 aria-label)。controller.open({ payload, anchor }) 可从代码打开(例如引导教程的一步),onPayloadChange 报告每次载荷变化。
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。
[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 在动画结束后触发。详见弹出层。
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" 避免读屏重复朗读。