"use client"; import { useState, useRef, useEffect, useCallback } from "react"; import { createPortal } from "react-dom"; import { useHelpMode } from "@/stores/helpModeStore"; interface HelpTooltipProps { text: string; children: React.ReactNode; /** Use block=true for full-width elements so the ? sits to the right without breaking layout */ block?: boolean; /** Set hidden=true to suppress the ? badge (e.g. collapsed sidebar items) */ hidden?: boolean; } export default function HelpTooltip({ text, children, block = false, hidden = false }: HelpTooltipProps) { const helpMode = useHelpMode(); const [open, setOpen] = useState(false); const [pos, setPos] = useState<{ x: number; y: number } | null>(null); const btnRef = useRef(null); const flyoutRef = useRef(null); const touchHandled = useRef(false); const [mounted, setMounted] = useState(false); useEffect(() => { setMounted(true); }, []); useEffect(() => { if (!helpMode) setOpen(false); }, [helpMode]); useEffect(() => { if (!open) return; const close = (e: MouseEvent | TouchEvent) => { const target = e.target as Node; if (!btnRef.current?.contains(target) && !flyoutRef.current?.contains(target)) { setOpen(false); } }; document.addEventListener("mousedown", close); document.addEventListener("touchstart", close, { passive: true }); return () => { document.removeEventListener("mousedown", close); document.removeEventListener("touchstart", close); }; }, [open]); const calcPos = useCallback(() => { if (!btnRef.current) return; const rect = btnRef.current.getBoundingClientRect(); const flyW = 210; const x = rect.right + 8 + flyW > window.innerWidth ? Math.max(4, rect.left - flyW - 8) : rect.right + 8; const y = Math.min(rect.top - 4, window.innerHeight - 130); setPos({ x, y }); }, []); const handleClick = useCallback((e: React.MouseEvent) => { if (touchHandled.current) { touchHandled.current = false; return; } e.stopPropagation(); calcPos(); setOpen((v) => !v); }, [calcPos]); const handleTouchEnd = useCallback((e: React.TouchEvent) => { e.preventDefault(); e.stopPropagation(); touchHandled.current = true; calcPos(); setOpen((v) => !v); }, [calcPos]); if (!helpMode || hidden) return <>{children}; const qBtn = ( ); return ( <> {block ? (
{children}
{qBtn}
) : ( {children} {qBtn} )} {open && mounted && pos && createPortal(
{text}
, document.body )} ); }