diff --git a/apps/desktop/src/components/ui/LightTooltip.vue b/apps/desktop/src/components/ui/LightTooltip.vue index 4f231524a..025a62876 100644 --- a/apps/desktop/src/components/ui/LightTooltip.vue +++ b/apps/desktop/src/components/ui/LightTooltip.vue @@ -20,10 +20,18 @@ const props = withDefaults( ); const triggerRef = ref(); +const tooltipRef = ref(); const show = ref(false); const x = ref(0); const y = ref(0); let timer: ReturnType | null = null; +let closeTimer: ReturnType | null = null; + +function clearCloseTimer() { + if (!closeTimer) return; + clearTimeout(closeTimer); + closeTimer = null; +} function triggerElement(): HTMLElement | undefined { const root = triggerRef.value; @@ -69,7 +77,7 @@ function isTriggerActive(): boolean { const el = triggerElement(); if (!el || !el.isConnected) return false; const active = document.activeElement; - return el.matches(":hover") || (active instanceof Node && el.contains(active)); + return el.matches(":hover") || tooltipRef.value?.matches(":hover") || (active instanceof Node && el.contains(active)); } function isDisabled(): boolean { @@ -104,12 +112,30 @@ function updatePosition() { function close() { clearTimer(); + clearCloseTimer(); show.value = false; removeGlobalListeners(); } function closeIfTriggerInactive() { - if (!isTriggerActive()) close(); + if (isTriggerActive()) { + clearCloseTimer(); + } else { + scheduleClose(); + } +} + +function scheduleClose() { + if (closeTimer) return; + closeTimer = setTimeout(() => { + closeTimer = null; + if (!isTriggerActive()) close(); + }, 100); +} + +function onPointerDown(e: PointerEvent) { + if (tooltipRef.value?.contains(e.target as Node)) return; + close(); } function addGlobalListeners() { @@ -118,7 +144,7 @@ function addGlobalListeners() { window.addEventListener("blur", close); document.addEventListener("visibilitychange", close); document.addEventListener("pointermove", closeIfTriggerInactive, true); - document.addEventListener("pointerdown", close, true); + document.addEventListener("pointerdown", onPointerDown, true); document.addEventListener("contextmenu", close, true); } @@ -128,7 +154,7 @@ function removeGlobalListeners() { window.removeEventListener("blur", close); document.removeEventListener("visibilitychange", close); document.removeEventListener("pointermove", closeIfTriggerInactive, true); - document.removeEventListener("pointerdown", close, true); + document.removeEventListener("pointerdown", onPointerDown, true); document.removeEventListener("contextmenu", close, true); } @@ -166,11 +192,20 @@ watch(