Skip to content

Stop the browser guest outliving the overlays drawn over it - #99

Merged
mutewinter merged 3 commits into
mainfrom
jmack/browser-panel-overlay-fixes
Aug 5, 2026
Merged

Stop the browser guest outliving the overlays drawn over it#99
mutewinter merged 3 commits into
mainfrom
jmack/browser-panel-overlay-fixes

Conversation

@mutewinter

@mutewinter mutewinter commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Three pre-existing faults in the task browser panel, all traceable to one fact: the guest is a <webview> on document.body, not an element in the page. 48 lines.

Split out of #97 so they aren't hostage to the browser-abstraction redesign.

1. Guests paint through app-wide dialogs

Open Settings, sign-in, the shortcut guide, the file viewer's expand modal, or the chat's image preview while a browser panel is showing, and the page keeps drawing on top of the dialog's dim layer. Nothing occludes a body-mounted guest, and opening a dialog isn't a tab switch — which is the only park signal useBrowserSlot otherwise receives. The panel now reports coverage itself.

2. Cmd+F dies after any of those closes

setBrowserFindOpener is a single slot. The overlay's own host claims it, clears it on unmount, and the panel — whose inputs never changed — never re-registers, so Cmd+F silently stops working until the panel is reopened. Both hooks now read one coverage value, so the panel gives up the slot and takes it back.

3. A load failure survives a session switch

targetId changes in place when the selected session changes — TaskView passes it as a prop with no key — so a failure from session A parks session B's guest behind an error notice naming A's URL. The failure is now stamped with the guest it happened on and filtered on read, which costs no extra render and never briefly shows a failed page as fine.

Verification

Driven in a running Studio: with the browser panel open and its guest showing, opening a studio dialog parks the guest (opacity 0.001, paint-host z-index) while the panel stays mounted, and closing it restores the guest over the slot at z-0.

pnpm check-and-test:ci green, 22/22.


Open in Devin Review

Summary by CodeRabbit

  • Bug Fixes
    • Prevented stale browser load errors from appearing after switching browser targets.
    • Improved browser behavior when covered by modals, file viewers, or previews.
    • Prevented covered or inactive browser panels from capturing the Cmd+F shortcut.
    • Cleared device emulation when a browser panel is covered.
    • Improved browser session handling when overlays open or close, helping maintain the correct active target and avoid displaying errors from another session.

Three faults in the task browser panel, all pre-existing and all from the guest
being a `<webview>` on `document.body` rather than an element in the page.

Nothing occludes it. An app-wide dialog -- settings, sign-in, the shortcut
guide, the file viewer's expand modal, the chat's image preview -- draws its dim
layer over the page and the guest keeps painting straight over the top of it.
Opening a dialog is also not a tab switch, which is the only park signal the
slot otherwise gets, so the panel now reports coverage itself.

Cmd+F stops working after any of those closes. The find opener is a single
slot; an overlay's own host claims it, clears it on unmount, and the panel --
whose inputs never changed -- never re-registers. Both hooks now read one
coverage value, so the panel gives up the slot and takes it back.

A load failure survives a session switch. `targetId` changes in place when the
selected session changes, with no remount, so the next session's guest is parked
behind an error notice naming the previous session's URL. The failure is stamped
with the guest it happened on and filtered on read, which costs no extra render
and never briefly shows a failed page as fine.
@coderabbitai

coderabbitai Bot commented Aug 4, 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: 8fbfbe93-7d29-4340-be23-a64d4e9da223

📥 Commits

Reviewing files that changed from the base of the PR and between ff799ea and b322bed.

📒 Files selected for processing (2)
  • apps/studio/src/client/components/task/browser-panel.tsx
  • apps/studio/src/client/hooks/use-guest-covered.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/studio/src/client/components/task/browser-panel.tsx

📝 Walkthrough

Walkthrough

The change detects when overlays cover browser guests. Covered guests are parked and excluded from Cmd+F registration. Browser load errors remain associated with their originating target.

Changes

Browser guest coverage

Layer / File(s) Summary
Overlay coverage state
apps/studio/src/client/atoms/studio-modal.ts, apps/studio/src/client/hooks/use-guest-covered.ts
Exports studio modal state and combines modal and preview states into useIsGuestCovered.
Covered browser host behavior
apps/studio/src/client/hooks/use-browser-slot.ts, apps/studio/src/client/hooks/use-browser-find.ts
Parks covered guests, clears emulation, and excludes covered panels from Cmd+F registration.
Target-aware browser panel integration
apps/studio/src/client/components/task/browser-panel.tsx
Passes coverage to browser hooks and displays load failures only for the target that produced them.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant TaskBrowserPanel
  participant useIsGuestCovered
  participant useBrowserSlot
  participant useBrowserFind
  TaskBrowserPanel->>useIsGuestCovered: Read overlay coverage
  TaskBrowserPanel->>useBrowserSlot: Pass covered state
  useBrowserSlot->>useBrowserSlot: Park guest and clear emulation
  TaskBrowserPanel->>useBrowserFind: Pass covered state
  useBrowserFind->>useBrowserFind: Skip Cmd+F registration
  TaskBrowserPanel->>TaskBrowserPanel: Match load errors to targetId
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly describes the main change: preventing the browser guest from remaining active above studio overlays.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
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 docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch jmack/browser-panel-overlay-fixes

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint install failed. For unrecoverable errors, disable the tool in CodeRabbit configuration.


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.

devin-ai-integration[bot]

This comment was marked as resolved.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
apps/studio/src/client/components/task/browser-panel.tsx (1)

185-200: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Ignore event handlers after the webview target changes.

targetId is changed only via the prop, while the listener cleanup runs only on active/targetId effect teardown (apps/studio/src/client/components/task/browser-panel.tsx:163-226). Between a rerender and cleanup, the old webview.addEventListener(...) callbacks still run with their captured targetId, and did-navigate/did-start-loading clear failure while did-fail-load replaces it with targetId: detail.targetId, affecting whichever target becomes current next. Keep a current rendered target ref, update it each render, and return from each callback when currentRef !== targetId. Add a regression test that rerenders the panel to another target, dispatches an old-target loading event before cleanup, and leaves the new target failure visible.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/studio/src/client/components/task/browser-panel.tsx` around lines 185 -
200, Update the webview event handlers in the panel component to ignore
callbacks from stale targets by maintaining a ref to the currently rendered
target, updating it on each render, and returning early from each handler when
the ref differs from its captured targetId. Ensure did-navigate,
did-start-loading, and did-fail-load cannot modify the new target’s failure
state after a target switch, and add a regression test covering an old-target
loading event dispatched before listener cleanup while preserving the new
target’s visible failure.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@apps/studio/src/client/components/task/browser-panel.tsx`:
- Around line 185-200: Update the webview event handlers in the panel component
to ignore callbacks from stale targets by maintaining a ref to the currently
rendered target, updating it on each render, and returning early from each
handler when the ref differs from its captured targetId. Ensure did-navigate,
did-start-loading, and did-fail-load cannot modify the new target’s failure
state after a target switch, and add a regression test covering an old-target
loading event dispatched before listener cleanup while preserving the new
target’s visible failure.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 92f2e620-5d21-47c9-b2de-3a8b5afa2de3

📥 Commits

Reviewing files that changed from the base of the PR and between 9744479 and ff799ea.

📒 Files selected for processing (5)
  • apps/studio/src/client/atoms/studio-modal.ts
  • apps/studio/src/client/components/task/browser-panel.tsx
  • apps/studio/src/client/hooks/use-browser-find.ts
  • apps/studio/src/client/hooks/use-browser-slot.ts
  • apps/studio/src/client/hooks/use-guest-covered.ts

The palette is the same shape as the dialogs the coverage hook already knows
about -- a Radix dialog with a dim layer, mounted app-wide -- but its open state
is its own atom rather than the studio-modal slot, so nothing was reporting it.
Cmd+K over a browser panel left the page painting over the palette.
The panel's webview listeners outlive `targetId` changing in place, by the frame
between the render and the effect teardown. A did-navigate or did-start-loading
arriving from the previous guest in that window cleared the failure whatever it
was stamped with, so returning to a failed session while the agent drove the one
you left dropped its error notice and unparked its guest over the slot. The
clear is now guarded on the listener's own guest, matching the write side.
@mutewinter
mutewinter merged commit 29ad64f into main Aug 5, 2026
4 checks passed
@mutewinter
mutewinter deleted the jmack/browser-panel-overlay-fixes branch August 5, 2026 17:10
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