v1.15.3.0 feat(browse): viewport auto / reset to unpin a fixed viewport (#1059)#1226
Open
gregario wants to merge 3 commits intogarrytan:mainfrom
Open
v1.15.3.0 feat(browse): viewport auto / reset to unpin a fixed viewport (#1059)#1226gregario wants to merge 3 commits intogarrytan:mainfrom
gregario wants to merge 3 commits intogarrytan:mainfrom
Conversation
Closes garrytan#1059. Once `browse viewport WxH` calls Playwright's `setViewportSize`, the viewport is pinned. There's no page-level API to undo it — the only way back to window-following is to rebuild the context. Skills that call `$B viewport` for responsive testing or breakpoint benchmarks were leaving the browser locked at that size for the rest of the session, with the visible Chrome window visibly larger than the viewport Claude was rendering into. Add `browse viewport auto` (alias `reset`) that takes the right path per connection mode: - **launched (headless):** full `recreateContext()` with `viewport: null`. Cookies, storage, URLs, and tab ownership ride through the standard save/restore. The new context truly follows window default. - **headed (persistent context):** `recreateContext()` is forbidden (the persistent context is tied to the user's Chrome window, can't be safely rebuilt). Instead, read `window.innerWidth` / `innerHeight` via `page.evaluate()` and resync the viewport once to match. Snapshot, not true follow — re-call after resize. The command help documents this constraint. Implementation notes: - New `viewportPinned: boolean` field on BrowserManager (default true, matching launch behavior). - `setViewport(w, h)` flips it back on so a re-pin after auto works. - `recreateContext()` builds two distinct contextOptions shapes: pinned uses `{viewport, deviceScaleFactor}`; unpinned uses `{viewport: null}` alone. Playwright rejects `deviceScaleFactor` with `viewport: null` (same constraint the existing headed-launch path already obeys). - `--scale` plus `auto`/`reset` is rejected — scale needs an explicit WxH to multiply. Tests live in a separate describe block at the end of commands.test.ts because context recreation renumbers tab IDs, and an existing test in the Tabs block (garrytan#664) hardcodes tab 1. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Closes #1059. Once
browse viewport WxHcalls Playwright'ssetViewportSize, the viewport is pinned. There's no page-level API to undo it — the only way back to window-following is to rebuild the context. Skills that called\$B viewportfor responsive testing or breakpoint benchmarks were leaving the browser locked at that size for the rest of the session, with the visible Chrome window noticeably larger than what Claude was rendering into.Before
After
Connection-mode-aware unpin
recreateContext()withviewport: nulllaunchPersistentContext)page.evaluate(window.innerWidth/Height)+setViewportSizeImplementation notes
viewportPinned: booleanonBrowserManager(default true, matches launch).setViewport(w, h)sets it true so re-pinning after auto works.recreateContext()builds two distinct context-option shapes. Important: Playwright rejectsdeviceScaleFactorwithviewport: null, so the unpinned path omits it. Same constraint the existing headed-launch path already obeys (line 359 —viewport: nullwith no DSF).--scaleplusauto/resetis rejected at the parser — scale needs an explicit WxH to multiply.Test plan
bun test browse/test/commands.test.ts— 227 pass (4 new tests in dedicated end-of-file describe block).viewport auto unpins a fixed size— pins, unpins, re-pins to a different size; the re-pin takes effect.viewport reset is an alias for auto— same path via the alias.viewport auto preserves cookies across context recreation— sets cookie, unpins, cookie still present.viewport auto rejects --scale combination— input validation.Files
browse/src/browser-manager.ts—unpinViewport()+ viewportPinned tracking + recreateContext branchingbrowse/src/write-commands.ts— viewportauto/resetparsing +--scalerejectionbrowse/src/commands.ts— usage docstringbrowse/test/commands.test.ts— 4 new testsVERSION,CHANGELOG.md— release v1.15.3.0🤖 Generated with Claude Code