Tooltip 使用手册
v1.24.5 · @snowui-design-system/components
许可阅读:首次阅读组件文档、源码或 npm 使用流程,先读完整 LICENSE;同任务同版本去重。公开 API 配置与内部实现修改分别按许可处理;全部组件使用统一运行包,源码权益以许可为准。
组件介绍
在悬停时展示简短说明,支持位置避让与连续切换动效,适合图标按钮和需要补充解释的内容。
使用选择
用于为现有控件提供简短补充提示。主要内容不能只放在 Tooltip;交互表单、菜单或复杂内容优先 Popover / Dialog。
放在触发元素内,不包裹触发器;未提供 children 时读取触发元素文字。
open 未传时由 hover 触发;显式 true / false 时由页面控制。主要内容和必要操作不能只藏在提示中。
快速开始
以下示例展示推荐的基本组合。更多场景与组合限制见后文。
API
未重新声明的继承能力请查所属基础组件文档;本表只列本组件源码具名公开属性。
使用边界与详细说明
关键字 (Keyword)
使用示例
布局模型
主布局模型:内联外壳布局。定义见 ../../../specs/maintainers/LayoutProtocol.md §12.4(源码参考:specs/maintainers/LayoutProtocol.md)。
Tooltip 的 Portal、定位、碰撞翻转属于组件行为;可见气泡内容本身按内联外壳布局管理:
.snowui-tooltip-content是 inline-level 外壳,内容整体 Hug。子内容通过
gap自然排列,不提供 Content Fill。气泡自身负责 padding / gap / radius / font-size / line-height,并通过
--snowui-tooltip-*-override变量允许外部覆盖。短内容保持 Hug;长内容先按最大宽度换行,再统一测量并选择方向,避免位置与换行互相反馈。长单词和 URL 允许断行。
内容支持鼠标移入保留显示;超高内容限制到安全区高度并内部滚动,移出后沿用共享隐藏延迟。
布局变量链:
智能行为
hover 延迟: 首次 hover 延迟
450ms显示;Tooltip 成功显示后,在300mscooldown 窗口内进入其他 Tooltip 时立即切换,不增加固定意图延迟。共享外框: 非受控 hover 模式始终复用页面级 Portal。离开当前触发器后的外框保留窗口与
300msskip-delay 一致;窗口内进入另一个 Tooltip 时取消隐藏,不重新播放出现动效。warm 切换的新内容提交后立即读取一次真实 Snippet 尺寸并定位,连续时间线在首个可用绘制帧进入 moving;后续内容尺寸变化仍由共享 ResizeObserver 合帧处理。二维连续切换: 仅当共享外框仍可见且切换到另一个触发器时执行。以气泡外框中心计算位移;中心距离不超过
240px,且hypot(dx / 可视宽度, dy / 可视高度) ≤ 0.25时,外框沿任意二维向量移动并同步改变宽高;超过阈值时直接定位。鼠标速度适配规则见下文第 11 项;以下为未提速时的基线。普通近距离位置与内容时间线为clamp(100ms + distance × 0.35ms/px, 120ms, 180ms)cubic ease-out 协调曲线。默认rapidRetarget=true;只有位置与内容交接尚未结束时再次改目标,才从当前可见画面接管并改用clamp(60ms + distance × 0.35ms/px, 90ms, 160ms)cubic ease-out 和0.02内容滞后。设为false时,中断仍使用普通协调时间线和0.02内容滞后。默认widthRebound=false,宽度跟随当前所选位置时间线直接收敛;显式设置widthRebound=true时,宽度独立使用1000ms欠阻尼弹簧,不被快速重定向缩短。位置与内容已完成、仅剩宽度回弹尾段时,新目标必须启动完整的普通内容交接,不得因宽度仍在回弹而压缩裁切揭示。两种模式都从当前可见宽度为新起点,不继承累计速度。top / bottom 以中心、left 以右边、right 以左边保持触发器侧锚点。具体值以 Tooltip continuous preset 为准。内容带拼接与协调时间线: 新旧目标 Tooltip 矩形最短距离不超过
4px时,旧、新内容沿外框移动向量拼成投影间距为16px的内容带。测量边界是完整 Snippet 的.snowui-tooltip-inner。外框位置与内容移动同帧开始,并在当前速度适配后的有界时程内完成对齐;旧内容层保留至宽度弹簧首次回弹点450ms。旧层清理只卸载 outgoing,不重置 incoming 偏移;incoming 继续按当前外框宽度补偿位置,直到宽度弹簧精确收敛,避免清理帧文字瞬间归零后又恢复造成抖动。运动中改目标时,以裁切窗口内实际可见面积更大的内容层接管,并在同一帧冻结实时视口矩形。圆角外框是唯一裁切窗口;距离超过4px时不拼接、不保留旧内容,但新内容必须在过渡中的外框内按最终 placement 保持局部对齐:top / bottom 水平居中,left 靠右,right 靠左;垂直方向 top 靠下、bottom 靠上、left / right 居中。重新出现规则: 外框已经隐藏后,不论间隔多久再次 hover,都重置上一次的坐标、尺寸和触发器记录;新一轮 Tooltip 首帧先完成不可见测量和定位,再直接从当前 hover 位置出现,不做位移动效和宽度变化动效。
冷却恢复: 离开 Tooltip 触发器超过
300ms后,恢复首次 hover 的450ms延迟。未成功显示就移开时,不进入立即显示模式。边界碰撞: 使用当前文档的 visualViewport(不可用时使用 window),iframe 内以 iframe 可视区为界。四边保留 16px;先限制外框宽度到 min(maxWidth, 可视宽度 − 32px),高度到可视高度 − 32px,再测量。依次尝试指定方向、反方向、其余两个方向,每个方向先沿交叉轴平移;优先完整落入安全区的位置,否则选择总溢出距离最小的位置并沿两轴移回安全区。窗口缩放、滚动、软键盘和内容尺寸变化均重新计算。连续切换(包括显式宽度回弹)也按安全区限制宽度和位置。Escape 关闭当前提示。安全区小于内容内边距的极小视口无法保证 16px。
动效感知关闭: 默认只在 Tooltip 已显示期间,以页面级单例监听触发元素与祖先的 transition / animation,以及后代真实元素的几何 transition;命中后立即卸载 Tooltip 并跳过退出动效。Button 已登记内容层的整体 transform 不改变触发器锚点,因此不触发关闭;其他后代几何过渡仍遵循原规则。后代 Logo / Icon 等装饰性 animation、颜色、背景、透明度以及
::before/::after伪元素 transition 不触发关闭;可通过dismissOnMotion={false}显式关闭。连续打断与性能: 位置或内容交接未结束又切换目标时,从当前外框和主要可见内容层的实时矩形重新计算下一段移动;旧时间线立即作废,不排队、不等待,也不得先跳到上一段终点。
rapidRetarget默认开启并使用90–160mscubic ease-out;关闭后使用普通120–180mscubic ease-out 协调曲线。独立宽度回弹的尾段不属于快速重定向窗口;此时切换目标使用完整普通内容时间线,同时宽度从当前可见值重新响应。warm 目标不得在内容已提交后再额外等待一个定位 rAF 和一个启动 rAF;切换专用同步测量只执行一次,不新增 Observer 或逐帧测量。合成提示只在moving阶段使用will-change。触发与减少动态效果: warm Tooltip 的每次目标变化都立即提交,不用固定意图延迟或 burst 窗口决定是否播放连续裁切;平滑指针速度只调整时长,不跳过连续裁切。
prefers-reduced-motion: reduce下,所有连续切换都立即定位并只显示新内容,不保留移动、宽高过渡或中间裁切状态。鼠标速度自适应: 有效鼠标速度只缩短所选基线时程:
min(基线时长, max(60ms, 外框中心距离 / 平滑速度 + 20ms)),速度单位为 px/ms。采用 32ms 指数平滑,超过 100ms 未采样则失效;慢移或无有效样本时保留距离基线。每次目标切换只读取一次速度,外框位置、高度、默认宽度与内容共用该时长;不在段内反复变速,速度适配不改变所选曲线和内容滞后,也不缩短显式 1000ms 宽度回弹。采样只在共享 Tooltip 活动且允许平滑动效时开启,只有一个被动监听;隐藏、卸载与 reduced-motion 时释放。首次 hover 延迟与受控 open 不受影响。交互宿主解析: Tooltip 直接放在 Link / Button 的内部包装层时,以最近的
a/button/role="link"/role="button"祖先作为 hover 命中与定位触发器;无交互祖先时保持以 Tooltip 的直接父元素为触发器。因此组件内部 label 在折叠态变为零宽或隐藏时,可见主操作仍保留完整 Tooltip 命中区。多实例性能边界: 非受控 Tooltip 实例只保留各自触发器的 enter / leave 监听。页面级 Overlay store 响应、动效关闭注册、
prefers-reduced-motion查询和 window scroll / resize 定位监听只由唯一共享 Portal host 承担;只有当前可见的受控 Tooltip 会额外注册自身定位监听。scroll、resize 与尺寸测量引起的重复定位请求通过requestAnimationFrame合并,每帧最多执行一次布局读取。内容所有权: 共享外框只在来源组件存活期间借用其内容Snippet。来源卸载时立即释放对应当前/旧层内容,不为退出动画继续读取已销毁来源;仅旧层来源卸载时,结束该段交接并保留存活目标。普通鼠标离开仍沿用原隐藏延迟及退出动画。
1) 气泡基础布局
渲染层通过 Portal 挂载到
document.body,定位方式为position: fixed。内容容器使用
inline-flex,并固定align-items: center、justify-content: flex-start。内容层可悬停;移入取消隐藏计时,移出恢复隐藏计时。
层级固定为
z-index: 9999,正文使用white-space: normal和overflow-wrap: anywhere。
2) Figma Token 映射
padding:--snowui-tooltip-padding→var(--padding-1) var(--padding-2)(上下 4,左右 8)gap:--snowui-tooltip-gap→var(--gap-2)(8)border-radius:--snowui-tooltip-radius→var(--radius-3)(12)font-size/line-height:--snowui-tooltip-font-size/--snowui-tooltip-line-height→var(--text-12)/var(--leading-12)
3) 视觉主题
variant="dark"(通过data-variant驱动):背景:
Static Black/80%+Static White/10%叠加文字:
Static White/100%
默认
variant="light":背景:
Black/4%文字:
Black/100%
4) 滤镜与阴影
Backdrop 保留完全透明的渐变绘制面,避免浏览器省略无背景绘制层的滤镜合成;颜色与生命周期动效仍由 Foreground 持有。
保留毛玻璃:
backdrop-filter: blur(1.25rem)(含-webkit-backdrop-filter)。Portal 必须保持在应用根节点隔离层之外,且自身不得被全局根节点选择器误加
isolation: isolate;否则毛玻璃虽有计算值,但无法采样应用根节点内的页面内容。根节点隔离规则见 StyleSpec.md §2.6.4(源码参考:specs/maintainers/StyleSpec.md)。当前版本已移除阴影,不使用
box-shadow。
5) 显隐与连续切换动效
非受控模式(
open未传入)下:首次鼠标进入触发器后延迟
450ms显示,显示成功后的 skip-delay 为300ms;自动根据视口边缘做碰撞翻转;
Tooltip 成功显示后,页面内其他 Tooltip 在
300mscooldown 窗口内立即响应;每个目标都从当前画面重定向连续裁切,旧时间线立即作废,不累积多段慢动效;连续切换触发器时复用同一个 Portal 外框;近距离切换沿任意二维方向移动,远距离切换直接定位;
连续移动使用独立的 transform wrapper 承接位置变化,Portal 锚点仍按现有定位语义更新;宽高由同一逐帧几何时间线更新;
新旧目标 Tooltip 矩形最短距离不超过
4px时,旧、新内容沿实际二维移动向量拼成投影间距为16px的内容带;切换使用速度适配后的普通 / 快速有界协调时间线;snowui-tooltip-size-shell的overflow: hidden与圆角共同形成唯一揭示边界;新旧目标 Tooltip 矩形最短距离超过
4px时,不拼接、不保留旧内容;新内容按最终 placement 在当前外框内保持局部对齐并随外框一起移动,不能在长内容切短内容时默认贴住左上角;动画中断时读取外框和当前内容层的实时矩形,再以各自当前可见位置作为下一段起点;
新一轮显示先完成不可见测量和定位,并为毛玻璃层保留一个不可见预绘制帧,再整体显示 Portal;稳定 Backdrop 首帧以完整 opacity 提供 blur,独立 Foreground 通过
getTooltipAppearMotion(finalPosition)执行 opacity、增强 scale 和 placement 定向滑入。top 从下向上、bottom 从上向下、left 从右向左、right 从左向右;具体数值以 Tooltip preset catalog 为准。Portal 与 Backdrop 不参与该出现动效,因此渐显不会削弱滤镜;外框隐藏后再次出现时重置运动基线,首帧直接定位到当前触发器,并在渐显结束后才开启后续尺寸动效;
离开触发器超过
300ms后恢复450ms首次延迟;生命周期出现只在
snowui-tooltip-foreground使用 Tooltip appear preset 的显式 opacity / scale / x / y 通道;transform origin 固定在靠近触发器的一侧中心,后续尺寸变化继续由 FrameIdle -> Active形态时序承接;内容宽高变化由
snowui-tooltip-size-shell保存明确宽高。普通尺寸变化继续消费 Frame size motion bridge;连续切换默认使用与外框位置相同的逐帧协调时间线并单调收敛,widthRebound显式开启时才由独立宽度弹簧产生轻微越界回弹。圆角和 padding 归 size shell,毛玻璃归稳定 Backdrop,背景色和内容归 Foreground;三个层级共享同一尺寸与裁切边界;top / bottom 方向使用触发器中心作为固定锚点,尺寸外壳用静态
transform: translateX(-50%)保持居中;left / right 方向使用触发器垂直中心作为固定锚点,尺寸外壳用静态transform: translateY(-50%)保持居中;宽高由 Frame size motion bridge 过渡,但居中偏移不参与过渡,因此连续切换和尺寸变化过程中 Tooltip 仍保持与触发器居中对齐;鼠标移开后按
300msskip-delay 保留外框以承接相邻触发器切换;窗口内命中新 Tooltip 时取消隐藏并直接复用。超过窗口仍未命中时把 Foreground Frame 切到Disappear状态,使用参考 transitions.dev Tooltip 的50ms退出动效:背景色和内容淡出并缩到98%;退出完成后再卸载包含 Backdrop 的共享外框。prefers-reduced-motion: reduce下关闭位置、宽高和内容带过渡,并同步清理旧内容层。
受控模式(
open传入)由外部状态直接控制显隐,不参与共享 warmup / cooldown 状态。当外部传入
loopMotion.preset="rotateClockwise"等循环默认能力时,Portal 外层 Frame 会直接承接该动效;因此 Tooltip 可见浮层本身可以连续旋转,且不会覆盖内部内容层的 appeartransform。
Tooltip 样式覆盖
先阅读 完整 LICENSE;同任务、同版本、同范围去重。
优先用组件公开 Props 匹配合适样式,尽可能保留原有视觉。确需改写时按 样式选择与改写顺序 使用自己的 class(含项目已有 Tailwind)或实例 style。以下名称来自源码实际消费的公开 override;先核对目标作用域,不修改私有 DOM。采用 SnowUI Token 时选择正确类别,外部应用不被要求安装一方 utilities。
Tooltip 类型与状态
必填属性:无具名必填属性。
可双向绑定:bind:open。
继承声明:FrameProps。继承能力以基类公开文档为准;Omit 中的字段已排除,不能按基类原样使用。
以下为公开属性实际引用的类型声明,来自源码;Svelte Snippet 表示内容片段,ComponentProps 表示对应组件的 Props。