From c13db8b8269a7d43a5401c55f5071fe5c29f87a3 Mon Sep 17 00:00:00 2001 From: Falkan Date: Wed, 18 Mar 2026 23:58:40 -0400 Subject: [PATCH] fix: tooltip flips above cursor when it would clip viewport bottom --- src/lib/actions/tooltip.ts | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/src/lib/actions/tooltip.ts b/src/lib/actions/tooltip.ts index 9344be4..8197e23 100644 --- a/src/lib/actions/tooltip.ts +++ b/src/lib/actions/tooltip.ts @@ -29,13 +29,22 @@ export function tooltip(node: HTMLElement, text: string) { if (!currentText) return; const el = getTooltipEl(); el.textContent = currentText; + el.classList.add('hu-tooltip--visible'); - // Position near cursor, clamped to viewport - const x = Math.min(e.clientX + 12, window.innerWidth - el.offsetWidth - 8); - const y = e.clientY + 20; + // Position near cursor, clamped to viewport with 8px margin + const margin = 8; + const w = el.offsetWidth; + const h = el.offsetHeight; + const x = Math.min(e.clientX + 12, window.innerWidth - w - margin); + // Try below cursor first; if it clips the bottom, flip above + let y = e.clientY + 20; + if (y + h + margin > window.innerHeight) { + y = e.clientY - h - 12; + } + // Final clamp: don't go above top of viewport + y = Math.max(margin, y); el.style.left = `${x}px`; el.style.top = `${y}px`; - el.classList.add('hu-tooltip--visible'); } function enter(e: MouseEvent) { @@ -47,8 +56,15 @@ export function tooltip(node: HTMLElement, text: string) { // Keep tooltip near cursor while hovering if (!tooltipEl?.classList.contains('hu-tooltip--visible')) return; const el = getTooltipEl(); - const x = Math.min(e.clientX + 12, window.innerWidth - el.offsetWidth - 8); - const y = e.clientY + 20; + const margin = 8; + const w = el.offsetWidth; + const h = el.offsetHeight; + const x = Math.min(e.clientX + 12, window.innerWidth - w - margin); + let y = e.clientY + 20; + if (y + h + margin > window.innerHeight) { + y = e.clientY - h - 12; + } + y = Math.max(margin, y); el.style.left = `${x}px`; el.style.top = `${y}px`; }