import { useState, useRef, useCallback, useEffect, type ReactNode } from "react"; import { computePosition, offset, flip, shift, type Placement } from "@floating-ui/dom"; interface TooltipProps { title: string; placement?: Placement; children: ReactNode; } export function Tooltip({ title, placement = "top", children }: TooltipProps) { const triggerRef = useRef(null); const tooltipRef = useRef(null); const [open, setOpen] = useState(false); const reposition = useCallback(() => { const trigger = triggerRef.current; const tip = tooltipRef.current; if (!trigger || !tip) return; computePosition(trigger, tip, { placement, strategy: "fixed", middleware: [offset(6), flip(), shift({ padding: 8 })], }).then(({ x, y }) => { tip.style.left = `${x}px`; tip.style.top = `${y}px`; }); }, [placement]); useEffect(() => { if (open) reposition(); }, [open, reposition]); if (!title) return <>{children}; return ( <> setOpen(true)} onMouseLeave={() => setOpen(false)} onFocus={() => setOpen(true)} onBlur={() => setOpen(false)} style={{ display: "inline-flex" }} > {children} {open && (
{title}
)} ); }