feat(tabs): split-tab context menu, and stop an open menu swallowing the next right-click - #211
Merged
Merged
Conversation
Right-clicking a unified split tab did nothing: only the session-tab button carried an onContextMenu handler, so a session merged into a split lost the menu its own tab had. The new menu is tab-scoped — broadcast input, a submenu that focuses one of the tab's panes, split apart into tabs, and close the tab with its session count. Anything acting on a single session stays on the pane header, where the target is unambiguous. Every layout mutation targets the active split tab, so each entry activates its tab first.
The menu sat above a full-screen backdrop that closed it on mousedown. That backdrop also caught the right-click meant for whatever was under it, so with one menu open, right-clicking another target did nothing at all — the stale menu simply stayed. The backdrop is gone; the menu closes from window-level mousedown and contextmenu capture instead, ignoring presses inside itself or inside a submenu portal. Capture runs before React's own handlers and does not preventDefault, so the event still reaches the element under the pointer and that element opens its own menu in the same event. Consequence worth knowing: a left-click outside now also reaches what it lands on, rather than being absorbed by the backdrop.
This was referenced Sep 7, 2026
Closed
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.
What
Right-clicking a unified split tab did nothing: only the session-tab button carried an
onContextMenu, so a session merged into a split lost the menu its own tab had. Reported as "the tab context menu doesn't appear on local shells" — local shells were a red herring, a split was the common factor.The new menu is tab-scoped; anything acting on a single session stays on the pane header, where the target is unambiguous:
broadcastActive, until now reachable only from the pane-header button1 · bash) because a duplicate-into-split yields two identical names; picking one focuses it (and un-maximizes a maximized sibling)Chasing that bug surfaced a second one, fixed in the follow-up commit: the menu sat above a full-screen backdrop that closed it on mousedown, and that backdrop also caught the right-click meant for whatever was under it. With one menu open, right-clicking another target did nothing at all and the stale menu stayed — the likely source of the "sometimes there's no menu" reports. The backdrop is gone; the menu now closes from window-level
mousedown/contextmenucapture, ignoring presses inside itself or inside a[data-menu-portal]submenu. Capture runs before React's handlers and does notpreventDefault, so the event reaches the element under the pointer and it opens its own menu in the same event.Every layout mutation targets the active split tab, so each entry activates its tab first.
Verification
Driven in the headless dev build, real pointer input:
Panes ›submenu still opens on hover and its entry still firestsc --noEmitclean. Full suite 521/522 files, 3991/3992 tests — the one failure,teamService.transport.test.ts > missing jwt triggers refresh, is a contention flake that passes 10/10 alone and touches nothing here.Caveat on the tests
ContextMenu.test.tsxdoes not prove the swallowed-right-click bug: jsdom'sfireEventdispatches straight to the node, so a covering backdrop is invisible to it and the old code passes the retarget assertion. The test covers the close semantics only, and says so in a comment; the hit-testing half is proven by the live run.Behavior change worth knowing
Without the backdrop, a left-click outside a menu now also reaches what it lands on, for every
ContextMenucaller (hosts, snippets, keychain, file pane, pane header).