diff --git a/src/components/Tooltip/use-tooltip-events.tsx b/src/components/Tooltip/use-tooltip-events.tsx index d223d29f..c1fd2d91 100644 --- a/src/components/Tooltip/use-tooltip-events.tsx +++ b/src/components/Tooltip/use-tooltip-events.tsx @@ -196,12 +196,12 @@ const useTooltipEvents = ({ const dataTooltipId = anchorSelector ? parseDataTooltipIdSelector(anchorSelector) : null resolveAnchorElementRef.current = (target: EventTarget | null) => { - const targetElement = target as HTMLElement | null - - if (!targetElement?.isConnected) { + if (!(target instanceof Element) || !target.isConnected) { return null } + const targetElement = target + if (dataTooltipId) { const matchedAnchor = resolveDataTooltipAnchor(targetElement, dataTooltipId) diff --git a/src/test/tooltip-interaction-behavior.spec.js b/src/test/tooltip-interaction-behavior.spec.js index 9928544a..b19b02b0 100644 --- a/src/test/tooltip-interaction-behavior.spec.js +++ b/src/test/tooltip-interaction-behavior.spec.js @@ -304,4 +304,22 @@ describe('tooltip interaction behavior', () => { addEventListenerSpy.mockRestore() }) + + test('ignores synthetic mouseover events targeting document', () => { + render( + <> + Hover Me + + , + ) + + expect(() => { + act(() => { + document.dispatchEvent(new MouseEvent('mouseover', { bubbles: true })) + }) + advanceTimers(60) + }).not.toThrow() + + expect(document.getElementById('document-target-test')).not.toBeInTheDocument() + }) }) diff --git a/src/utils/resolve-data-tooltip-anchor.ts b/src/utils/resolve-data-tooltip-anchor.ts index 321f3f3c..85386375 100644 --- a/src/utils/resolve-data-tooltip-anchor.ts +++ b/src/utils/resolve-data-tooltip-anchor.ts @@ -1,8 +1,8 @@ -function resolveDataTooltipAnchor(targetElement: HTMLElement, tooltipId: string) { - let currentElement: HTMLElement | null = targetElement +function resolveDataTooltipAnchor(targetElement: Element, tooltipId: string) { + let currentElement: Element | null = targetElement while (currentElement) { - if (currentElement.dataset.tooltipId === tooltipId) { + if (currentElement instanceof HTMLElement && currentElement.dataset.tooltipId === tooltipId) { return currentElement } currentElement = currentElement.parentElement