Skip to content

fix(watch-fork-star-popup): portal popup out of the stargazers anchor#39

Merged
rrbe merged 1 commit into
mainfrom
fix/star-popup-click-leak
Jun 26, 2026
Merged

fix(watch-fork-star-popup): portal popup out of the stargazers anchor#39
rrbe merged 1 commit into
mainfrom
fix/star-popup-click-leak

Conversation

@rrbe

@rrbe rrbe commented Jun 26, 2026

Copy link
Copy Markdown
Owner

Problem

Clicking a stargazer (avatar / name / blank space) in the star popup still navigated to the stargazers list instead of the user's profile — the bug #35 tried, but failed, to fix.

The root cause: the star/fork counters are GitHub's own <a href=".../stargazers"> / <button>. The popup was appended inside them, so the popup's user links became nested anchors trapped inside the stargazers anchor.

The earlier stopPropagation fix couldn't work:

  • GitHub binds clicks in the capture phase; our bubble-phase handler ran too late.
  • Nested <a> is invalid HTML with no spec'd activation target, and stopPropagation doesn't override default navigation anyway.

Fix

Stop nesting the popup inside the anchor entirely — portal it to <body> and position it with position: fixed computed from the counter's rect. Now:

  • User links are plain anchors → navigate natively to the profile, keeping Cmd/Ctrl/middle-click → new tab for free.
  • Blank-area clicks hit no anchor → nothing happens.
  • No stopPropagation hack needed.

Changes

  • watch-fork-star-popup.ts: append popup to document.body; position via getBoundingClientRect() in show().
  • Remove the stopPropagation interceptor and the re-attach MutationObserver (popup is no longer a child of the counter, so GitHub re-rendering the counter is harmless).
  • Add reapOrphanedPopups() (tracked via a WeakMap) so SPA navigations don't leak orphaned body-level popups.
  • Cancel the close timer on counter re-entry to avoid a flicker, now that leaving the counter for the popup fires mouseleave.
  • content.css: .bg-wfs-popup position: absolutefixed (top/left set by JS).

Tests

  • New assertions: the popup lives in <body> and is not inside the stargazers anchor; orphaned popups are reaped on re-inject.
  • Full suite green: 228 passed.

To verify locally: reload the unpacked extension from dist/, open a repo page, hover Star, and click a stargazer — it should open the user's profile, not the stargazers list.

The star/fork counters are GitHub's own `<a href=".../stargazers">` /
`<button>`, and the popup was appended inside them. That trapped the popup's
user links as nested anchors inside the stargazers anchor, so clicking a
stargazer (avatar, name, or blank space) resolved to the wrapping anchor and
navigated to the stargazers list instead of the user's profile.

The earlier stopPropagation fix (#35) couldn't help: GitHub binds clicks in
the capture phase (our bubble-phase handler runs too late), and nested anchors
are invalid HTML with no spec'd activation target — and stopPropagation can't
override the default navigation anyway.

Portal the popup to <body> and position it with `position: fixed` so it lives
outside any anchor. User links then navigate natively (keeping Cmd/Ctrl/middle-
click new-tab for free) and blank-area clicks hit nothing.

- Drop the stopPropagation hack and the re-attach MutationObserver (the popup
  is no longer a child of the counter, so GitHub re-rendering it is harmless).
- Reap orphaned body popups on inject so SPA navigations don't leak them.
- Cancel the close timer on counter re-entry to avoid a flicker now that
  leaving the counter for the popup fires mouseleave.
@rrbe rrbe merged commit 112a31f into main Jun 26, 2026
1 check passed
@rrbe rrbe deleted the fix/star-popup-click-leak branch June 26, 2026 04:14
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