Skip to content

fix(devtools): claim the inspect click in the capture phase - #516

Open
thedv91 wants to merge 1 commit into
TanStack:mainfrom
thedv91:feat-inspect-click-capture-phase
Open

fix(devtools): claim the inspect click in the capture phase#516
thedv91 wants to merge 1 commit into
TanStack:mainfrom
thedv91:feat-inspect-click-capture-phase

Conversation

@thedv91

@thedv91 thedv91 commented Aug 22, 2026

Copy link
Copy Markdown

🎯 Changes

Holding the inspect hotkey and clicking an element:

Before After
A button with an onClick source opens, and the button fires too source opens, the button stays untouched
Anything inside a modal or dropdown that stops click propagation nothing at all — no source, and the button fires source opens, the button stays untouched

SourceInspector listened on document in the bubble phase. By then React has already dispatched its synthetic onClick and a router link has already navigated, and preventDefault() cannot undo either — it only cancels the browser's own default action. The second row is the sharper one: an ancestor calling stopPropagation(), which is every overlay that closes on an outside click, stops the event before it reaches document, so the handler never ran and an inspect click inside a modal silently did nothing.

{ capture: true } fixes both, and costs the page nothing: the handler returns immediately unless the hotkey is held over an element carrying data-tsd-source, and it already performs the open-in-editor or copy itself rather than relying on anything downstream.

Still open, and out of scope here: mousedown/pointerdown are untouched, so a drag or focus wired to those still starts on an inspect click.

Verificationexamples/react/basic, with a throwaway component holding a plain <button onClick> and a button inside a <div> whose native click listener calls stopPropagation(). On main, an inspect click on the plain button copied …/inspect-click-repro.tsx:35:7 and took its counter 1 → 2; the same click inside the modal took that counter 1 → 2 and copied nothing. With this change both copied their path and neither counter moved, while ordinary clicks without the hotkey still increment both. source-inspector.test.tsx pins the modal case; it fails on main.

✅ Checklist

  • I have followed the steps in the Contributing guide.
  • I have tested this code locally with pnpm test:pr.

🚀 Release Impact

  • This change affects published code, and I have generated a changeset.

Summary by CodeRabbit

  • Bug Fixes
    • Source inspection now works reliably inside modals, dropdowns, and other elements that stop click propagation.
    • Inspected elements no longer activate unintentionally when opening their source.
    • Ordinary clicks continue to behave normally when inspection mode is inactive.

@coderabbitai

coderabbitai Bot commented Aug 22, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 3f853594-c275-487e-98bf-a815abfdcad0

📥 Commits

Reviewing files that changed from the base of the PR and between 566d39b and de3c8dd.

📒 Files selected for processing (3)
  • .changeset/inspect-click-capture-phase.md
  • packages/devtools/src/components/source-inspector.test.tsx
  • packages/devtools/src/components/source-inspector.tsx

Included review availability: Your plan provides up to 2 included reviews per hour; 1 remains after this review.


📝 Walkthrough

Walkthrough

The source inspector now handles armed clicks during the document capture phase. Tests cover propagation-stopping ancestors and ordinary clicks without the inspection hotkey. A patch changeset documents the update.

Changes

Source inspection click handling

Layer / File(s) Summary
Capture-phase inspection handling
packages/devtools/src/components/source-inspector.tsx, packages/devtools/src/components/source-inspector.test.tsx, .changeset/inspect-click-capture-phase.md
SourceInspector uses a named document capture handler for inspection clicks. Tests verify source activation through propagation-stopping ancestors and preserve unarmed clicks. A patch changeset records the behavior.
Estimated code review effort: 2 (Simple) ~10 minutes

Merge Risk: ⚪ Minimal · up to de3c8

The change prevents inspect clicks from triggering underlying button actions or being swallowed by stopping ancestors, while preserving ordinary clicks. No actionable merge-blocking risk remains beyond normal checks and review.

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant document
  participant SourceInspector
  participant Ancestor
  User->>document: Click an inspected element
  document->>SourceInspector: Invoke onInspectClick during capture
  SourceInspector->>SourceInspector: Open or copy the source
  document->>Ancestor: Continue dispatch for an unarmed click
  Ancestor-->>User: Handle the ordinary click
Loading
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the primary change: handling inspect clicks during the capture phase.
Description check ✅ Passed The description explains the motivation, behavior, verification, scope, checklist completion, and generated changeset.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 2 files. (1 skipped: 1 unsupported.)
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

The source inspector listened for clicks in the bubble phase, so by the time
it ran the page had already acted on the click: React had dispatched its
synthetic onClick, a router link had navigated. preventDefault() cancels only
the browser's own default action, so none of that could be undone.

Worse, any ancestor calling stopPropagation() -- a modal or dropdown that
closes on an outside click -- stopped the event before it reached document,
so inspecting inside one silently did nothing at all.

Claiming the click in the capture phase fixes both. It costs the page nothing:
the handler returns immediately unless the inspect hotkey is held over an
element carrying data-tsd-source, and it already performs the open-in-editor
or copy itself.
@thedv91
thedv91 force-pushed the feat-inspect-click-capture-phase branch from de3c8dd to 153a720 Compare August 22, 2026 03:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant