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

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
Contributor

🎯 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 works 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.
  • Improvements
    • Source inspection uses the configured source URL when available, while retaining the default source-opening behavior.

@coderabbitai

coderabbitai Bot commented Aug 22, 2026

Copy link
Copy Markdown

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository: TanStack/devtools/.coderabbit.yaml

Review profile: CHILL

Plan: Advanced

Run ID: 8e619bf4-c7d0-4373-beab-6718d1c342bc

📥 Commits

Reviewing files that changed from the base of the PR and between de3c8dd and 9d8b0e6.

📒 Files selected for processing (2)
  • packages/devtools/src/components/source-inspector.test.tsx
  • packages/devtools/src/components/source-inspector.tsx

Included review availability: Your plan provides up to 4 included reviews per hour; 3 remain after this review.


📝 Walkthrough

Walkthrough

The source inspector now handles clicks during the document capture phase and uses configured or default source URLs. 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
A named document click handler runs during capture and uses configured or default source URLs. Tests cover propagation-stopping ancestors and preserve ordinary clicks when the inspection hotkey is not held. A patch changeset records the update.

Estimated code review effort: 2 (Simple) | ~10 minutes

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant document
  participant SourceInspector
  participant Ancestor
  User->>document: Click inspected element
  document->>SourceInspector: Invoke onInspectClick during capture
  SourceInspector->>SourceInspector: Build source URL and fetch
  SourceInspector-->>document: Prevent inspected click from reaching target listener
  User->>document: Click without inspection hotkey
  document->>Ancestor: Dispatch ordinary click
Loading

Suggested reviewers: alemtuzlak

Merge Risk: ⚪ Minimal · up to 9d8b0

No actionable issue remains in the reviewed capture-phase change; it is ready to merge after normal checks.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the main change: handling inspect clicks during the capture phase.
Description check ✅ Passed The description explains the motivation, behavior before and after the change, verification results, scope limits, checklist completion, and changeset status.
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…
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 a new PR

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.

@nx-cloud

nx-cloud Bot commented Aug 24, 2026

Copy link
Copy Markdown

🤖 Nx Cloud AI Fix Eligible

An automatically generated fix could have helped fix failing tasks for this run, but Self-healing CI is disabled for this workspace. Visit workspace settings to enable it and get automatic fixes in future runs.

To disable these notifications, a workspace admin can disable them in workspace settings.


View your CI Pipeline Execution ↗ for commit 153a720

Command Status Duration Result
nx affected --targets=test:eslint,test:sherif,t... ❌ Failed 2m 21s View ↗
nx run-many --target=test:e2e --parallel=1 --pr... ✅ Succeeded 1m 16s View ↗
nx run-many --targets=build --exclude=examples/... ✅ Succeeded 34s View ↗

☁️ Nx Cloud last updated this comment at 2026-08-24 16:30:52 UTC

@pkg-pr-new

pkg-pr-new Bot commented Aug 24, 2026

Copy link
Copy Markdown
More templates

@tanstack/angular-devtools

npm i https://pkg.pr.new/@tanstack/angular-devtools@516

@tanstack/devtools

npm i https://pkg.pr.new/@tanstack/devtools@516

@tanstack/devtools-a11y

npm i https://pkg.pr.new/@tanstack/devtools-a11y@516

@tanstack/devtools-bundler-core

npm i https://pkg.pr.new/@tanstack/devtools-bundler-core@516

@tanstack/devtools-client

npm i https://pkg.pr.new/@tanstack/devtools-client@516

@tanstack/devtools-rspack

npm i https://pkg.pr.new/@tanstack/devtools-rspack@516

@tanstack/devtools-ui

npm i https://pkg.pr.new/@tanstack/devtools-ui@516

@tanstack/devtools-utils

npm i https://pkg.pr.new/@tanstack/devtools-utils@516

@tanstack/devtools-vite

npm i https://pkg.pr.new/@tanstack/devtools-vite@516

@tanstack/devtools-event-bus

npm i https://pkg.pr.new/@tanstack/devtools-event-bus@516

@tanstack/devtools-event-client

npm i https://pkg.pr.new/@tanstack/devtools-event-client@516

@tanstack/preact-devtools

npm i https://pkg.pr.new/@tanstack/preact-devtools@516

@tanstack/react-devtools

npm i https://pkg.pr.new/@tanstack/react-devtools@516

@tanstack/solid-devtools

npm i https://pkg.pr.new/@tanstack/solid-devtools@516

@tanstack/svelte-devtools

npm i https://pkg.pr.new/@tanstack/svelte-devtools@516

@tanstack/vue-devtools

npm i https://pkg.pr.new/@tanstack/vue-devtools@516

commit: 153a720

@thedv91
thedv91 force-pushed the feat-inspect-click-capture-phase branch from 153a720 to dbd66b8 Compare September 23, 2026 16:58
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 dbd66b8 to 9d8b0e6 Compare September 23, 2026 17:04

This branch has not been deployed

No deployments
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.

2 participants