Skip to content

Commit

Permalink
fix(component): fix an issue related to conflicting pointer and focus…
Browse files Browse the repository at this point in the history
… events hiding the tooltip unexpectedly (#3592)

Co-authored-by: Zherdetska Alona, IT21.1 <[email protected]>
Co-authored-by: Philipp Gfeller <[email protected]>
  • Loading branch information
3 people authored Oct 4, 2024
1 parent 4c9a491 commit ac68940
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 7 deletions.
5 changes: 5 additions & 0 deletions .changeset/red-lies-lick.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@swisspost/design-system-components': patch
---

Fixed an issue related to conflicting pointer and focus events hiding the tooltip unexpectedly in some situations. The tooltip now behaves as expected in this situation.
3 changes: 2 additions & 1 deletion packages/components/src/components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -311,8 +311,9 @@ export namespace Components {
/**
* Programmatically display the tooltip
* @param target An element with [data-tooltip-target="id"] where the tooltip should be shown
* @param triggeredByFocus A boolean indicating if the tooltip was triggered by a focus event.
*/
"show": (target: HTMLElement) => Promise<void>;
"show": (target: HTMLElement, triggeredByFocus?: boolean) => Promise<void>;
/**
* Toggle tooltip display
* @param target An element with [data-tooltip-target="id"] where the tooltip should be shown
Expand Down
27 changes: 25 additions & 2 deletions packages/components/src/components/post-tooltip/post-tooltip.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ const tooltipTargetAttributeSelector = `[${tooltipTargetAttribute}]`;
/**
* Global event listener to show tooltips. This is globalized so that triggers that are rendered
* async will still work without the need to set listeners on the element itself
*
* This handler manages both pointer and focus events to properly trigger tooltips.
* If the event is a focus event (e.g., keyboard navigation), pointer events are ignored to avoid
* interference with tooltip behavior.
* @param e Event
* @returns
*/
Expand All @@ -34,7 +38,11 @@ const globalInterestHandler = (e: PointerEvent | FocusEvent) => {
const tooltipTarget = targetElement.getAttribute(tooltipTargetAttribute);
if (!tooltipTarget || tooltipTarget === '') return;
const tooltip = document.getElementById(tooltipTarget) as HTMLPostTooltipElement;
void tooltip?.show(targetElement);

// Determine if the tooltip was triggered by a focus event
const triggeredByFocus = e.type === 'focusin';
void tooltip?.show(targetElement, triggeredByFocus);

if (hideTooltipTimeout) {
window.clearTimeout(hideTooltipTimeout);
hideTooltipTimeout = null;
Expand Down Expand Up @@ -98,6 +106,7 @@ const triggerObserver = getAttributeObserver(tooltipTargetAttribute, patchAccess
})
export class PostTooltip {
private popoverRef: HTMLPostPopovercontainerElement;
private wasOpenedByFocus: boolean = false;

@Element() host: HTMLPostTooltipElement;

Expand Down Expand Up @@ -186,10 +195,22 @@ export class PostTooltip {
/**
* Programmatically display the tooltip
* @param target An element with [data-tooltip-target="id"] where the tooltip should be shown
* @param triggeredByFocus A boolean indicating if the tooltip was triggered by a focus event.
*/
@Method()
async show(target: HTMLElement) {
async show(target: HTMLElement, triggeredByFocus = false) {
if (this.delayed) await timeout(OPEN_DELAY);

// 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);
}

Expand Down Expand Up @@ -223,9 +244,11 @@ export class PostTooltip {

/**
* Pointer or focus left the tooltip, initiate the hiding process
* Re-enable pointer events when the tooltip is no longer in focus or hovered
*/
private handleInterestLost() {
globalHideTooltip(this);
this.host.style.pointerEvents = 'auto';
}

render() {
Expand Down
9 changes: 5 additions & 4 deletions packages/components/src/components/post-tooltip/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,16 @@ Type: `Promise<void>`



### `show(target: HTMLElement) => Promise<void>`
### `show(target: HTMLElement, triggeredByFocus?: boolean) => Promise<void>`

Programmatically display the tooltip

#### Parameters

| Name | Type | Description |
| -------- | ------------- | ---------------------------------------------------------------------------- |
| `target` | `HTMLElement` | An element with [data-tooltip-target="id"] where the tooltip should be shown |
| Name | Type | Description |
| ------------------ | ------------- | ---------------------------------------------------------------------------- |
| `target` | `HTMLElement` | An element with [data-tooltip-target="id"] where the tooltip should be shown |
| `triggeredByFocus` | `boolean` | A boolean indicating if the tooltip was triggered by a focus event. |

#### Returns

Expand Down

0 comments on commit ac68940

Please sign in to comment.