fix: allow clicking links and copying text from tooltips

This commit is contained in:
N1C4T
2026-01-09 16:37:31 +04:00
parent 1474881aad
commit d7deb55d02
4 changed files with 28 additions and 8 deletions

1
.gitignore vendored
View File

@@ -42,3 +42,4 @@ next-env.d.ts
# local notes
notes.md
AGENT.md

View File

@@ -24,7 +24,7 @@ import { Tooltip, GlobalStyles, LoadingSkeleton } from '@/components/common';
export default function Home() {
// All the state we need to make this thing work
const { tooltip, show: showTooltip, hide: hideTooltip, tooltipMouseEnter, tooltipMouseLeave } = useTooltip();
const { tooltip, show: showTooltip, hide: hideTooltip, tooltipMouseEnter, tooltipMouseLeave, setTooltipRef } = useTooltip();
const {
selectedDistro,
@@ -203,7 +203,7 @@ export default function Home() {
onClick={clearFocus}
>
<GlobalStyles />
<Tooltip tooltip={tooltip} onMouseEnter={tooltipMouseEnter} onMouseLeave={tooltipMouseLeave} />
<Tooltip tooltip={tooltip} onMouseEnter={tooltipMouseEnter} onMouseLeave={tooltipMouseLeave} setRef={setTooltipRef} />
{/* Header */}
<header ref={headerRef} className="pt-8 sm:pt-12 pb-8 sm:pb-10 px-4 sm:px-6 relative" style={{ zIndex: 1 }}>

View File

@@ -7,9 +7,10 @@ interface TooltipProps {
tooltip: TooltipState | null;
onMouseEnter: () => void;
onMouseLeave: () => void;
setRef?: (el: HTMLDivElement | null) => void;
}
export function Tooltip({ tooltip, onMouseEnter, onMouseLeave }: TooltipProps) {
export function Tooltip({ tooltip, onMouseEnter, onMouseLeave, setRef }: TooltipProps) {
const [current, setCurrent] = useState<TooltipState | null>(null);
const [visible, setVisible] = useState(false);
const timeoutRef = useRef<NodeJS.Timeout | null>(null);
@@ -62,6 +63,7 @@ export function Tooltip({ tooltip, onMouseEnter, onMouseLeave }: TooltipProps) {
return (
<div
ref={setRef}
role="tooltip"
className="fixed hidden md:block pointer-events-auto z-[9999]"
style={{ left: current.x, top: current.y - 10 }}

View File

@@ -20,6 +20,12 @@ export function useTooltip() {
const hideTimeout = useRef<NodeJS.Timeout | null>(null);
const isOverTrigger = useRef(false);
const isOverTooltip = useRef(false);
const tooltipRef = useRef<HTMLDivElement | null>(null);
// Allow setting the tooltip element ref from the Tooltip component
const setTooltipRef = useCallback((el: HTMLDivElement | null) => {
tooltipRef.current = el;
}, []);
const cancel = useCallback(() => {
if (showTimeout.current) {
@@ -74,7 +80,18 @@ export function useTooltip() {
}, [tryHide]);
useEffect(() => {
const dismiss = () => {
const dismiss = (e: MouseEvent) => {
// Don't dismiss if clicking inside the tooltip
if (tooltipRef.current && tooltipRef.current.contains(e.target as Node)) {
return;
}
cancel();
isOverTrigger.current = false;
isOverTooltip.current = false;
setTooltip(null);
};
const dismissOnScroll = () => {
cancel();
isOverTrigger.current = false;
isOverTooltip.current = false;
@@ -82,20 +99,20 @@ export function useTooltip() {
};
const handleKeyDown = (e: KeyboardEvent) => {
if (e.key === 'Escape') dismiss();
if (e.key === 'Escape') dismissOnScroll();
};
window.addEventListener('mousedown', dismiss, true);
window.addEventListener('scroll', dismiss, true);
window.addEventListener('scroll', dismissOnScroll, true);
window.addEventListener('keydown', handleKeyDown);
return () => {
cancel();
window.removeEventListener('mousedown', dismiss, true);
window.removeEventListener('scroll', dismiss, true);
window.removeEventListener('scroll', dismissOnScroll, true);
window.removeEventListener('keydown', handleKeyDown);
};
}, [cancel]);
return { tooltip, show, hide, tooltipMouseEnter, tooltipMouseLeave };
return { tooltip, show, hide, tooltipMouseEnter, tooltipMouseLeave, setTooltipRef };
}