fix(web): 基础控件 Tooltip - 子元素可触发并保留键盘可达性 (#560)

Original-Commit: 38b5909fa78902048345ad8d8e00248660830ad5
fix(web): 基础控件 Tooltip - 子元素可触发并保留键盘可达性

react-aria-components 的 TooltipTrigger 通过 context 下发 hover/focus 处理与 triggerRef,
只有消费该上下文的组件才会真正挂上;原来包一层普通 span,既不读 context 也拿不到 ref,
所以悬停/聚焦都不弹气泡(有定位也无基准)。

包装层改为 Focusable + excludeFromTabOrder:悬停与聚焦都能触发、气泡有定位基准,
外层不占 Tab 位,键盘焦点仍落在内层控件上,导航顺序不变。
This commit is contained in:
AetherNo2332
2026-09-21 06:22:00 +08:00
committed by ddCat
parent edcf7bc7c0
commit 5e3bc01161

View File

@@ -1,5 +1,5 @@
import type { ReactNode } from "react";
import { Tooltip as RACTooltip, TooltipTrigger, type Placement } from "react-aria-components";
import { Focusable, Tooltip as RACTooltip, TooltipTrigger, type Placement } from "react-aria-components";
import { cn } from "@/lib/utils";
@@ -42,7 +42,16 @@ export function Tooltip({ title, placement = "top", delay = 350, className, chil
return (
<TooltipTrigger delay={delay}>
<span className="inline-flex">{children}</span>
{/*
* RAC 1.21 的 TooltipTrigger 通过 context 下发 hover/focus 处理与 triggerRef,
* 只有消费该上下文的组件才会真正挂上(原生 <span>/<button> 不会读)。直接套
* 普通 span 的写法因此既没有触发事件、也没有定位基准,鼠标悬停永远不弹。
* Focusable 消费该上下文并把属性和 ref 合并到子元素:聚焦与悬停都可用,弹窗
* 也有定位基准;外层不占 Tab 位,键盘焦点落在内层控件上后冒泡触发。
*/}
<Focusable excludeFromTabOrder>
<span className="inline-flex">{children}</span>
</Focusable>
<RACTooltip placement={PLACEMENT_MAP[placement]} offset={6} className={cn("z-50 max-w-64 rounded-md border border-border bg-surface-strong px-2 py-1 text-xs leading-relaxed text-foreground shadow-md", "ra-pop-in", className)}>
{title}
</RACTooltip>