From 2c12d5ad5ee9b9baf713c7b92056b07e303efb1a Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Mon, 2 Feb 2026 17:28:04 -0800 Subject: [PATCH] Fix tooltip flash and misposition on mobile (#20) - Temporarily expand tooltip for accurate size measurement before positioning - Use @media (hover: hover) to prevent CSS :hover triggering on touch tap - Await position calculation before showing tooltip --- src/App.svelte | 17 ++++++++++++++--- src/app.css | 13 ++++++++++++- 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/src/App.svelte b/src/App.svelte index 93d1693..7b9b68e 100644 --- a/src/App.svelte +++ b/src/App.svelte @@ -20,6 +20,12 @@ const tooltip = trigger.querySelector('.tooltip-content'); if (!tooltip) return; + // Temporarily expand tooltip for measurement (keep invisible) + tooltip.style.maxHeight = 'none'; + tooltip.style.padding = '10px'; + tooltip.style.visibility = 'hidden'; + tooltip.style.opacity = '0'; + const { x, y } = await computePosition(trigger, tooltip, { placement: 'top', middleware: [ @@ -31,7 +37,12 @@ Object.assign(tooltip.style, { left: `${x}px`, - top: `${y}px` + top: `${y}px`, + // Clear temporary styles - CSS will handle final visibility + maxHeight: '', + padding: '', + visibility: '', + opacity: '' }); } @@ -39,7 +50,7 @@ const isTouchDevice = window.matchMedia('(any-pointer: coarse)').matches; // Touch devices: position and show on click - document.addEventListener('click', (e) => { + document.addEventListener('click', async (e) => { const trigger = e.target.closest('.tooltip-trigger'); if (trigger) { e.preventDefault(); @@ -47,7 +58,7 @@ const wasActive = trigger.classList.contains('active'); document.querySelectorAll('.tooltip-trigger.active').forEach(t => t.classList.remove('active')); if (!wasActive) { - positionTooltip(trigger); + await positionTooltip(trigger); trigger.classList.add('active'); } } else { diff --git a/src/app.css b/src/app.css index 7bd5997..e84f320 100644 --- a/src/app.css +++ b/src/app.css @@ -807,7 +807,18 @@ body { max-height: 0; } -.tooltip-trigger:hover>.tooltip-content, +/* Only use hover on devices with real hover support (not touch) */ +@media (hover: hover) { + .tooltip-trigger:hover>.tooltip-content { + opacity: 1; + visibility: visible; + padding: 10px; + max-height: none; + overflow: visible; + } +} + +/* Active state for touch devices (controlled by JS) */ .tooltip-trigger.active>.tooltip-content { opacity: 1; visibility: visible;