Skip to content

fix(scraps): Stop tooltip content clicks from triggering ancestors - #121155

Open
TkDodo wants to merge 2 commits into
masterfrom
tkdodo/fix/tooltip-click-propagation
Open

fix(scraps): Stop tooltip content clicks from triggering ancestors#121155
TkDodo wants to merge 2 commits into
masterfrom
tkdodo/fix/tooltip-click-propagation

Conversation

@TkDodo

@TkDodo TkDodo commented Aug 4, 2026

Copy link
Copy Markdown
Collaborator

Tooltip content is portaled to document.body, but React events still bubble through the React component tree — not the DOM tree. So a click inside a tooltip reaches whatever interactive element the tooltip is nested within and fires its action. Clicking a link inside the tooltip, or pressing a button in it, or even selecting the tooltip text, would trigger the ancestor.

This bites whenever an interactive element is an ancestor of the <Tooltip> (as opposed to being the tooltip's trigger, which is a harmless sibling of the content). Concrete cases:

  • A FeatureBadge in a tab header: clicking the badge tooltip navigates the tab.
  • A component like Version dropped inside a clickable row: clicking the copy button in its tooltip triggers the row.
  • A Button whose label carries an InfoText: a click aimed at a link inside the tip fires the button (e.g. finalizing a release).

The fix stops the interaction-initiating events (click, mousedown, pointerdown) at the portaled overlay, so tooltip content can never trigger the element the tooltip is attached to. This covers both event models — react-router <Link> fires on click, react-aria tabs and menu items fire on pointerdown. Non-triggering events (text selection, keyboard) are left untouched.

Version previously worked around this with a manual stopPropagation on its tooltip content; that's now redundant and is removed.

before:

tooltip-before.mov

after:

tooltip-after.mov

Tooltip content is portaled to the document body, but React events still bubble through the React component tree — so clicking inside a tooltip reaches the interactive ancestor the tooltip is nested in (a Link, tab, menu item, or a Button wrapping an InfoText label) and fires its action.

This is easy to hit with a hoverable tooltip whose content is interactive or selectable: e.g. a Button whose label carries an InfoText would finalize on a click aimed at a link inside the tip. Stop the interaction-initiating events at the portaled overlay so tooltip content never triggers the element the tooltip is attached to.

Removes the now-redundant manual stopPropagation workaround in Version.
@github-actions github-actions Bot added the Scope: Frontend Automatically applied to PRs that change frontend components label Aug 4, 2026
@github-actions

github-actions Bot commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Story previews

Preview the stories changed in this PR on the Vercel deployment:

Preview deployment: https://sentry-qudlsl0zg.sentry.dev

@TkDodo

TkDodo commented Aug 4, 2026

Copy link
Copy Markdown
Collaborator Author

bugbot run

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit 3871a37. Configure here.

@TkDodo
TkDodo marked this pull request as ready for review August 4, 2026 13:06
@TkDodo
TkDodo requested a review from a team as a code owner August 4, 2026 13:06
Comment on lines +108 to +110
onClick={stopPropagation}
onMouseDown={stopPropagation}
onPointerDown={stopPropagation}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

as written, these will override existing handlers for those events on overlayProps. we should create a merged function that calls the user-supplied callback after stopPropagation

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Scope: Frontend Automatically applied to PRs that change frontend components

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants