Allow opening in the side panel as well as the popup (re-target of #134) - #137
Merged
Merged
Conversation
* Allow opening in the side panel as well as the popup (#121) The popup closes the moment anything else takes focus, so clicking into the page to check a replacement dismisses it and the terms have to be typed again. Settings now offers "Open in: Popup | Side panel". Both surfaces load the same assets/popup.html, popup.js and style.css — there is no second copy of the UI. background/surface.ts registers the side panel with ?surface=sidepanel, and that query string is the only thing popup.ts keys its layout off: the panel fills the width it is given, pins the action buttons to the bottom of the window, and drops the history list's height cap, which only exists to keep the popup inside Chrome's 600px. Clearing default_popup is the part that makes the toolbar button work: while a popup is registered Chrome opens it and never fires action.onClicked, so openPanelOnActionClick has nothing to act on. Neither that nor the panel behaviour survives a browser restart, so both are reapplied on startup as well as on install and whenever the preference changes. side_panel.default_path in the manifest stays a plain path. A manifest Chrome rejects stops the extension loading at all, and --load-extension does not work in this environment to prove a query string there is accepted — the unmodified manifest fails to install identically — so the query is applied through sidePanel.setOptions instead, which runs before the panel can ever be opened. The panel outlives a tab, unlike the popup, so it recounts when the user switches tab or navigates; a count left over from a tab they have since moved away from is worse than no count. Also: - chrome.sidePanel needs Chrome 114. Rather than setting minimum_chrome_version and cutting older browsers off from updates, the preference is hidden where the API is missing. - The toggle-popup command had no handler, so Ctrl+Shift+S has never done anything. It now opens whichever surface is configured. - Switching to the side panel from inside the popup opens the panel there and then, rather than leaving the user to work out they must click the toolbar button again. Documented in the help page, and translated into all ten locales. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Add a side panel open/close button to the header The preference under the cog is for choosing a default; this is for switching surface there and then. In the popup the icon opens the side panel and closes the popup behind it; in the panel it closes the panel. There is no sidePanel.close(), so the panel closes its own window, which is also how the popup dismisses itself once the panel has taken over. The window id is looked up on load rather than in the click handler: sidePanel.open has to be called while the user gesture is still in effect, and awaiting windows.getCurrent() inside the handler risks spending it. The sixth icon exposed a rule that has never worked. #header form set flex-wrap: nowrap, but the markup carried bootstrap's .flex-wrap, whose !important beat it — with five icons they happened to fit, so nobody noticed. The class is gone, the form no longer shrinks, and the gap is 4px, so all six icons and the full title fit across 320px. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Move the header icons onto their own row Six icons and the title were fighting over 320px: the icons ended up crowded together and the title was trimmed to "Search and Repl...". The icons now sit on a row of their own beneath the title, with the full width to spread across. That row costs about 27px, which took every section back over the 600px at which Chrome scrolls the whole popup, so the header padding drops to py-2, the gap above the icons is 6px, and the history list cap comes down to 340px. Measured across all ten locales: the tallest is now Russian at exactly 600. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Group the header icons instead of putting them on their own row A row of six evenly spaced glyphs under the title read as undifferentiated. They are back on the title row, in two groups with a divider between them: the two that only tell you something (help, about) and the four that do something (history, settings, saved rules, side panel). Fitting all six and the untruncated title across 320px needed the width back: the icons are 16px rather than 18px, the gap within a group is 3px, and the title span loses a redundant .mx-1 that doubled up with the flex gap. Title renders in full at 320px. Back on one row, every section has room again: the tallest is Russian at 575 against Chrome's 600px cap, so the history list cap returns to 380px. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Split the header into a title line and a tab strip Help and about only ever open documentation; history, settings, saved rules and the side panel toggle change what you are looking at. The first pair now sits on the title line, and the other four form a full-bleed tab strip beneath it, sharing the width equally. The underline marking the open panel spans the whole tab rather than just the glyph. The strip costs about 26px, so the body panel's vertical padding drops to 12px and the history list cap to 330px. Measured across all ten locales: the tallest is Russian at 593 against Chrome's 600px cap. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
forgetso
force-pushed
the
help-rules-popup-refresh
branch
from
September 21, 2026 22:21
67e8bdf to
97026bc
Compare
Merged
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.
Re-opens the side panel work for
master. Closes #121.Important
#134 was merged into the wrong base and never reached
master. It targetedhelp-rules-popup-refresh, but that branch had already been squash-merged intomaster47 minutes earlier as #133 (7ec3d0b). Merging #134 therefore added the side panel to a branch nothing was pulling from.This PR is the same branch targeted at
master. The diff is the side panel alone — #133's content is already inmastervia the squash, so it does not reappear here.The content is unchanged from #134 and was reviewed there. Summary:
One UI, two surfaces
The popup closes the moment anything else takes focus, so clicking into the page to check a replacement dismisses it and the terms have to be typed again. Settings offers Open in: Popup | Side panel, and the header carries a button to switch there and then.
Both surfaces load the same
assets/popup.html,popup.jsandstyle.css— no second copy of the UI.background/surface.tsregisters the panel with?surface=sidepanel, and that query string is the only thingpopup.tskeys its layout off: the panel fills its width, pins the action buttons to the bottom, and drops the history list's height cap. Measured at 320, 400 and 560px: no overflow, footer pinned.Making the toolbar button reach it
Clearing
default_popupis the part that matters — while a popup is registered Chrome opens it and never firesaction.onClicked, soopenPanelOnActionClickhas nothing to act on. Neither that nor the panel behaviour survives a browser restart, so both are reapplied ononStartup.side_panel.default_pathstays a plain path: a manifest Chrome rejects stops the extension loading at all, and--load-extensioninstalls nothing in this environment (the unmodified manifest fails identically), so that could not be verified. The query is applied throughsidePanel.setOptions()instead, which always runs before the panel can be opened.Header
Six icons and the title could not share 320px, so the header is split by what the icons do — help and about stay on the title line, and history, settings, saved rules and the side panel toggle form a full-bleed tab strip sharing the width equally:
The strip costs ~26px, which matters because Chrome scrolls the entire popup past 600px; body padding drops to 12px and the history cap to 330px. Across all ten locales the tallest is Russian at 593.
This exposed a rule that had never worked:
#header formsetflex-wrap: nowrap, but the markup carried bootstrap's.flex-wrap, whose!importantbeat it.Also
chrome.sidePanelneeds Chrome 114; the preference is hidden where the API is missing rather than settingminimum_chrome_versionand cutting older browsers off from updates.toggle-popupcommand had no handler, soCtrl+Shift+Shad never done anything. It now opens whichever surface is configured.popup— the issue asks for a choice, not a replacement.Checks
npm run checkspasses — typecheck, lint, format, 643 tests, build. 16 coversurface.ts, including the Chrome-113 path and the browser refusing the call.Worth a smoke test on an unpacked build: manifest loads, panel opens from the button and from
Ctrl+Shift+S, andsetOptionslands before first use.🤖 Generated with Claude Code