如何解决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
相关产品推荐
相关产品推荐

