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

如何解决Shadcn UI/Radix UI中关闭Dialog后Tooltip自动重开的问题

问题:关闭Dialog后Tooltip自动重开的修复方案

问题背景

使用Shadcn UI/Radix UI实现Tooltip与Dialog组合功能,核心代码如下:

<Dialog
  open={isModalOpen}
  onOpenChange={async (open) => {
    setIsModalOpen(open);
    closeTooltip();
  }}
>
  <TooltipProvider>
    <Tooltip>
      <DialogTrigger asChild>
        <TooltipTrigger asChild>
          <Button
            variant="ghost"
            id="browse-prompt"
            ref={triggerRef}
            className="grid aspect-square h-9 w-9 place-items-center rounded-full p-0 hover:bg-accent"
          >
            <Chrome className="h-5 w-5 text-white" />
            <span className="sr-only">Browse Prompts</span>
          </Button>
        </TooltipTrigger>
      </DialogTrigger>
      <TooltipContent>
        <h3 className="text-base font-semibold">Browse Prompt</h3>
        <p>Find useful prompts from others</p>
        <Arrow color="white" fill="white"></Arrow>
      </TooltipContent>
      {/* Dialog Content */}
    </Tooltip>
  </TooltipProvider>
</Dialog>

遇到的问题:关闭Dialog后Tooltip会自动弹出,尝试在Dialog的onOpenChange中手动关闭Tooltip状态、触发按钮mouseout事件、点击文档等方法均无效,期望关闭Dialog后Tooltip仅在重新hover按钮时才显示。

修复方案

方案1:受控Tooltip状态+延迟重置(通用方案)

通过受控状态控制Tooltip显示,并在Dialog关闭后延迟重置Tooltip状态,避免焦点事件触发Tooltip:

import { useState, useEffect } from 'react';
import { Dialog, DialogTrigger, DialogContent } from '@/components/ui/dialog';
import { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider } from '@/components/ui/tooltip';
import { Button } from '@/components/ui/button';
import { Chrome } from 'lucide-react';

export function BrowsePromptButton() {
  const [isModalOpen, setIsModalOpen] = useState(false);
  const [isTooltipOpen, setIsTooltipOpen] = useState(false);

  // Dialog关闭时延迟重置Tooltip状态
  useEffect(() => {
    if (!isModalOpen) {
      const timer = setTimeout(() => setIsTooltipOpen(false), 100);
      return () => clearTimeout(timer);
    }
  }, [isModalOpen]);

  return (
    <Dialog open={isModalOpen} onOpenChange={setIsModalOpen}>
      <TooltipProvider>
        <Tooltip open={isTooltipOpen} onOpenChange={setIsTooltipOpen}>
          <DialogTrigger asChild>
            <TooltipTrigger asChild>
              <Button
                variant="ghost"
                id="browse-prompt"
                className="grid aspect-square h-9 w-9 place-items-center rounded-full p-0 hover:bg-accent"
              >
                <Chrome className="h-5 w-5 text-white" />
                <span className="sr-only">Browse Prompts</span>
              </Button>
            </TooltipTrigger>
          </DialogTrigger>
          <TooltipContent>
            <h3 className="text-base font-semibold">Browse Prompt</h3>
            <p>Find useful prompts from others</p>
          </TooltipContent>
          <DialogContent>
            {/* 这里放Dialog内容 */}
            <p>Dialog Content</p>
          </DialogContent>
        </Tooltip>
      </TooltipProvider>
    </Dialog>
  );
}

原理:Dialog关闭后Radix会自动将焦点送回触发按钮,而Tooltip默认会响应焦点事件触发显示。通过延迟100ms重置Tooltip状态,确保焦点事件处理完成后再关闭Tooltip,避免状态被覆盖。

方案2:修改Tooltip触发条件(简单方案)

如果不需要Tooltip在焦点时显示,直接将Tooltip的触发方式改为仅监听hover:

<Tooltip trigger="hover" open={isTooltipOpen} onOpenChange={setIsTooltipOpen}>
  {/* 原有Tooltip内容 */}
</Tooltip>

原理:去掉Tooltip的焦点触发逻辑,仅在鼠标hover时显示,Dialog关闭后焦点回到按钮不会触发Tooltip。

内容的提问来源于stack exchange,提问作者DevEnma

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 21:05:01