From 740b7ee92cc97ab578bec34fb137f846bfe3c8b8 Mon Sep 17 00:00:00 2001 From: leagrdv Date: Fri, 22 Nov 2024 14:44:35 +0100 Subject: [PATCH 1/2] fix(components): delayed tooltip shown even after blur event --- .changeset/clean-windows-think.md | 5 +++++ .../components/src/components/post-tooltip/post-tooltip.tsx | 5 +++++ 2 files changed, 10 insertions(+) create mode 100644 .changeset/clean-windows-think.md diff --git a/.changeset/clean-windows-think.md b/.changeset/clean-windows-think.md new file mode 100644 index 0000000000..074a9b499d --- /dev/null +++ b/.changeset/clean-windows-think.md @@ -0,0 +1,5 @@ +--- +'@swisspost/design-system-components': patch +--- + +Fixed bug that showed delayed tooltip even after blur event. diff --git a/packages/components/src/components/post-tooltip/post-tooltip.tsx b/packages/components/src/components/post-tooltip/post-tooltip.tsx index 2ce0237ac7..1ec72f3ae6 100644 --- a/packages/components/src/components/post-tooltip/post-tooltip.tsx +++ b/packages/components/src/components/post-tooltip/post-tooltip.tsx @@ -19,6 +19,7 @@ let tooltipInstances = 0; let hideTooltipTimeout: number = null; const tooltipTargetAttribute = 'data-tooltip-target'; const tooltipTargetAttributeSelector = `[${tooltipTargetAttribute}]`; +let globalCurrentTarget: HTMLElement; /** * Global event listener to show tooltips. This is globalized so that triggers that are rendered @@ -34,6 +35,7 @@ const globalInterestHandler = (e: PointerEvent | FocusEvent) => { const targetElement = (e.target as HTMLElement).closest( tooltipTargetAttributeSelector, ) as HTMLElement; + globalCurrentTarget = targetElement; if (!targetElement || !('getAttribute' in targetElement)) return; const tooltipTarget = targetElement.getAttribute(tooltipTargetAttribute); if (!tooltipTarget || tooltipTarget === '') return; @@ -201,6 +203,9 @@ export class PostTooltip { async show(target: HTMLElement, triggeredByFocus = false) { if (this.delayed) await timeout(OPEN_DELAY); + // If focus or pointer event is not on the button anymore, don't show the tooltip + if (globalCurrentTarget !== target) return; + // Determine if the tooltip was opened by a focus event this.wasOpenedByFocus = triggeredByFocus; From 179bbfdf6b146ef526644a2192d89074e4d470f7 Mon Sep 17 00:00:00 2001 From: leagrdv Date: Tue, 26 Nov 2024 12:03:21 +0100 Subject: [PATCH 2/2] fix quick focus/blur glitch --- .../components/post-tooltip/post-tooltip.tsx | 44 ++++++++++++------- 1 file changed, 28 insertions(+), 16 deletions(-) diff --git a/packages/components/src/components/post-tooltip/post-tooltip.tsx b/packages/components/src/components/post-tooltip/post-tooltip.tsx index 1ec72f3ae6..f902cdc433 100644 --- a/packages/components/src/components/post-tooltip/post-tooltip.tsx +++ b/packages/components/src/components/post-tooltip/post-tooltip.tsx @@ -4,7 +4,7 @@ import { version } from '@root/package.json'; import isFocusable from 'ally.js/is/focusable'; import 'long-press-event'; import { getAttributeObserver } from '@/utils/attribute-observer'; -import { checkEmptyOrType, timeout } from '@/utils'; +import { checkEmptyOrType } from '@/utils'; const OPEN_DELAY = 650; // matches HTML title delay @@ -20,6 +20,7 @@ let hideTooltipTimeout: number = null; const tooltipTargetAttribute = 'data-tooltip-target'; const tooltipTargetAttributeSelector = `[${tooltipTargetAttribute}]`; let globalCurrentTarget: HTMLElement; +let tooltipTimeout = null; /** * Global event listener to show tooltips. This is globalized so that triggers that are rendered @@ -36,7 +37,10 @@ const globalInterestHandler = (e: PointerEvent | FocusEvent) => { tooltipTargetAttributeSelector, ) as HTMLElement; globalCurrentTarget = targetElement; - if (!targetElement || !('getAttribute' in targetElement)) return; + if (!targetElement || !('getAttribute' in targetElement)) { + clearTimeout(tooltipTimeout); + return; + } const tooltipTarget = targetElement.getAttribute(tooltipTargetAttribute); if (!tooltipTarget || tooltipTarget === '') return; const tooltip = document.getElementById(tooltipTarget) as HTMLPostTooltipElement; @@ -201,22 +205,30 @@ export class PostTooltip { */ @Method() async show(target: HTMLElement, triggeredByFocus = false) { - if (this.delayed) await timeout(OPEN_DELAY); - - // If focus or pointer event is not on the button anymore, don't show the tooltip - if (globalCurrentTarget !== target) return; - - // Determine if the tooltip was opened by a focus event - this.wasOpenedByFocus = triggeredByFocus; - - // Disable pointer events if triggered by focus, otherwise enable them - if (this.wasOpenedByFocus) { - this.host.style.pointerEvents = 'none'; + const showTooltip = () => { + // If focus or pointer event is not on the button anymore, don't show the tooltip + if (globalCurrentTarget !== target) return; + + // Determine if the tooltip was opened by a focus event + this.wasOpenedByFocus = triggeredByFocus; + + // Disable pointer events if triggered by focus, otherwise enable them + if (this.wasOpenedByFocus) { + this.host.style.pointerEvents = 'none'; + } else { + this.host.style.pointerEvents = 'auto'; + } + + this.popoverRef.show(target); + }; + + if (this.delayed) { + tooltipTimeout = setTimeout(() => { + showTooltip(); + }, OPEN_DELAY); } else { - this.host.style.pointerEvents = 'auto'; + showTooltip(); } - - this.popoverRef.show(target); } /**