From 3e9ba6c017217514540030e421266ca7356f95e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mathias=20Gla=CC=88ser?= Date: Mon, 21 Sep 2026 16:24:20 +0200 Subject: [PATCH] fix: coordinate tooltip pointer and touch state --- scripts/tooltip-overlays.js | 39 ++++++++++++++++++++++++++++--------- 1 file changed, 30 insertions(+), 9 deletions(-) diff --git a/scripts/tooltip-overlays.js b/scripts/tooltip-overlays.js index 2de1bc4..1c75a7c 100644 --- a/scripts/tooltip-overlays.js +++ b/scripts/tooltip-overlays.js @@ -1,6 +1,7 @@ (function initTooltipOverlayModule() { let tooltipId = 0; const states = new WeakMap(); + const tooltipStates = new Set(); const getViewport = () => ({ width: window.visualViewport?.width || window.innerWidth, @@ -156,6 +157,11 @@ }; const openTooltip = (state) => { + tooltipStates.forEach((otherState) => { + if (otherState !== state) { + closeTooltip(otherState); + } + }); movePanelToPortal(state); setOpenState(state, true); positionTooltip(state); @@ -219,10 +225,14 @@ wrap.dataset.tooltipInit = 'true'; wrap.dataset.tooltipPlacement = 'bottom'; states.set(wrap, state); + tooltipStates.add(state); ensureAccessibility(state); setOpenState(state, false); - wrap.addEventListener('pointerenter', () => { + wrap.addEventListener('pointerenter', (event) => { + if (event.pointerType !== 'mouse') { + return; + } if (state.dismissed) { return; } @@ -231,6 +241,9 @@ }); wrap.addEventListener('pointerleave', (event) => { + if (event.pointerType !== 'mouse') { + return; + } state.hoverTrigger = false; state.dismissed = false; if (!state.panel.contains(event.relatedTarget)) { @@ -238,14 +251,20 @@ } }); - state.panel.addEventListener('pointerenter', () => { + state.panel.addEventListener('pointerenter', (event) => { + if (event.pointerType !== 'mouse') { + return; + } if (!state.dismissed) { state.hoverPanel = true; openTooltip(state); } }); - state.panel.addEventListener('pointerleave', () => { + state.panel.addEventListener('pointerleave', (event) => { + if (event.pointerType !== 'mouse') { + return; + } state.hoverPanel = false; state.dismissed = false; closeIfInactive(state); @@ -268,7 +287,6 @@ }); state.trigger.addEventListener('click', (event) => { - event.stopPropagation(); togglePinned(state); }); @@ -314,14 +332,17 @@ }); observer.observe(document.body, { childList: true, subtree: true }); - document.addEventListener('click', (event) => { - document.querySelectorAll('.sg-tooltip-wrap').forEach((wrap) => { - const state = states.get(wrap); - if (state && !wrap.contains(event.target) && !state.panel.contains(event.target)) { + const closeFromOutside = (event) => { + tooltipStates.forEach((state) => { + if (!state.wrap.contains(event.target) && !state.panel.contains(event.target)) { closeTooltip(state); } }); - }); + }; + + document.addEventListener('pointerdown', closeFromOutside, true); + document.addEventListener('touchstart', closeFromOutside, true); + document.addEventListener('click', closeFromOutside, true); const repositionOpenTooltips = () => { document.querySelectorAll('.sg-tooltip-wrap[data-tooltip-open="true"]').forEach((wrap) => {