Skip to content

[BUG] 6.0.6 regression (#1278): tooltips don't resolve on non-HTMLElement anchors (SVG/MathML) — resolveDataTooltipAnchor narrowed to instanceof HTMLElement #1279

@aramarakelyan88

Description

@aramarakelyan88

Describe the bug

The fix for #1277 (PR #1278, released in 6.0.6) narrowed the delegated anchor resolver to instanceof HTMLElement. Any anchor whose data-tooltip-id sits on a non-HTMLElement — most commonly an <svg> icon used as a tooltip trigger — no longer resolves, so the tooltip silently never opens. This worked in 6.0.5 and earlier.

Root cause

src/utils/resolve-data-tooltip-anchor.ts:

while (currentElement) {
  if (currentElement instanceof HTMLElement && currentElement.dataset.tooltipId === tooltipId) {
    return currentElement
  }
  currentElement = currentElement.parentElement
}

The property the resolver actually needs, dataset, is not exclusive to HTMLElement. It is provided by the HTMLOrSVGElement mixin, which is implemented by HTMLElement, SVGElement, and MathMLElement. Narrowing by the HTMLElement subclass — rather than by the dataset capability — silently drops valid SVGElement anchors today (and MathMLElement anchors as well).

Notably, the library already uses the broader form elsewhere, in isScrollable:

if (!(node instanceof HTMLElement || node instanceof SVGElement)) {
  return false
}

…and #1277 itself suggested an instanceof Element guard.

Reproduction

import { Tooltip } from 'react-tooltip'

<svg data-tooltip-id="t" width="16" height="16"><circle cx="8" cy="8" r="8" /></svg>
<Tooltip id="t" content="Hello" />
  • 6.0.5: hovering the SVG shows the tooltip.
  • 6.0.6: nothing happens — the anchor never matches.

Suggested fix

Match by the capability rather than a specific subclass. Keeping instanceof Element still preserves the #1277 fix (document, window, and text nodes are not Elements), and reading dataset defensively covers HTMLElement, SVGElement, MathMLElement, and any future dataset-bearing element:

while (currentElement) {
  if (currentElement instanceof Element && currentElement.dataset?.tooltipId === tooltipId) {
    return currentElement
  }
  currentElement = currentElement.parentElement
}

(TS note: dataset lives on the HTMLOrSVGElement mixin rather than on Element, so a small cast/guard may be needed.)

If you'd prefer to mirror the existing isScrollable style, the minimal equivalent is:

if (
  (currentElement instanceof HTMLElement ||
    currentElement instanceof SVGElement ||
    currentElement instanceof MathMLElement) &&
  currentElement.dataset.tooltipId === tooltipId
) {
  return currentElement
}

Workaround

Wrap the icon in an HTMLElement (e.g. a <span>) and put data-tooltip-id on the wrapper, so the resolver walks up from the <svg> to a matching element.

Version

6.0.6

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions