如何嵌套Radix UI的Tooltip与Popover组件?解决自动触发问题
Radix UI Popover下拉菜单内首个Tooltip自动触发的修复方案
我在用Radix UI构建带下拉菜单的按钮时遇到了问题——下拉菜单打开时,里面第一个带Tooltip的按钮会自动触发Tooltip,第二个却正常只在 hover 时触发。我实现的代码如下:
const MyButton = forwardRef((props: any, forwardedRef: any) => ( <button {...props} ref={forwardedRef} /> )); let btn = ( <Popover.Root> <Tooltip.Provider> <Tooltip.Root> <Tooltip.Trigger asChild> <Popover.Trigger asChild> <MyButton>Button with tooltip</MyButton> </Popover.Trigger> </Tooltip.Trigger> <Tooltip.Content>Content</Tooltip.Content> </Tooltip.Root> </Tooltip.Provider> <Popover.Portal> <Popover.Content> <Tooltip.Provider> <Tooltip.Root> <Tooltip.Trigger asChild> <MyButton>Nested button with tooltip 1</MyButton> </Tooltip.Trigger> <Tooltip.Content>Tooltip nested1</Tooltip.Content> </Tooltip.Root> </Tooltip.Provider> <Tooltip.Provider> <Tooltip.Root> <Tooltip.Trigger asChild> <MyButton>Nested button with tooltip 2</MyButton> </Tooltip.Trigger> <Tooltip.Content>Tooltip nested2</Tooltip.Content> </Tooltip.Root> </Tooltip.Provider> </Popover.Content> </Popover.Portal> </Popover.Root> ); return btn;
问题原因
Popover打开后,Radix UI默认会自动将焦点移到内容区域的第一个可交互元素上。而Tooltip组件默认监听focus事件来触发显示,第一个按钮刚好成为焦点元素,导致Tooltip自动弹出;第二个按钮未获得焦点,所以仅在hover时触发。
修复方案
方案1:限制Tooltip仅通过hover触发
给第一个Tooltip的Root组件添加trigger="hover"属性,让它只响应鼠标悬停事件:
<Tooltip.Root trigger="hover"> <Tooltip.Trigger asChild> <MyButton>Nested button with tooltip 1</MyButton> </Tooltip.Trigger> <Tooltip.Content>Tooltip nested1</Tooltip.Content> </Tooltip.Root>
方案2:关闭Popover的自动聚焦行为
给Popover.Content添加autoFocus={false},阻止下拉菜单打开时自动聚焦到第一个元素:
<Popover.Content autoFocus={false}> {/* 内部Tooltip按钮 */} </Popover.Content>
方案3:指定Popover的初始聚焦目标
如果需要保留自动聚焦,但不想聚焦到Tooltip按钮,可以通过initialFocusRef指定其他元素作为初始焦点,比如添加一个不可见的焦点占位元素:
import { useRef } from 'react'; // ... const initialFocusRef = useRef<HTMLDivElement>(null); let btn = ( <Popover.Root> {/* ...其他代码 */} <Popover.Portal> <Popover.Content initialFocusRef={initialFocusRef}> <div ref={initialFocusRef} tabIndex={-1} className="sr-only"></div> {/* 内部Tooltip按钮 */} </Popover.Content> </Popover.Portal> </Popover.Root> );
方案选择建议
- 若Tooltip仅需hover触发,方案1最直接简洁;
- 若不需要Popover自动聚焦,方案2操作简单;
- 若要保留自动聚焦逻辑但避免Tooltip误触发,方案3更灵活。
内容的提问来源于stack exchange,提问作者Kernier
相关产品推荐
相关产品推荐

