You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何嵌套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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 23:27:23