feat(desktop): New Tab screen for the right pane
Merged
SA
5d ago+885+885+012345678901234567890123456789-307-307-012345678901234567890123456789
The right pane's "+" now opens a full New Tab pane instead of a dropdown, following Satya's right-pane audit (#general, 10-27). It has three sections, titled like the cloud sidebar's hover card (layout "A2" from the mocks):
- Tools: Terminal, Browser, Changes, Files, Review, Pages (plus Desktop on a sandbox and Mobile behind its flag), with their hotkeys. These are the center empty state's rows (
EmptyTabActionButton). - Pages: this workspace's 4 newest pages, as the right pane's Pages view shows them (
PagesListCard). - Pull requests: every PR linked to this workspace, newest first, in any state, as one-line hover-card rows (
CloudPullRequestRow), from the host's PR history (pullRequests.historyByWorkspaces), so it works for local and cloud workspaces.
Screenshots: https://app.superset.sh/page/right-pane-new-tab-screen-zupovt
What changed
- "+" adds a New Tab, and an overflowing tab bar scrolls it into view. Splits in the right pane (header button, Split Horizontally/Vertically) put a New Tab in the new split; the center still splits to a terminal.
- Opening an empty right pane adds a New Tab. This only reacts to the pane opening or its layout loading, so closing the last tab still closes the pane.
- Picking anything (tool, page, PR) replaces the New Tab in place and focuses the new pane. If that page, or the workspace's one PR pane, is already open, it is retargeted and focused instead, and the New Tab stays.
- Hotkeys: when a New Tab is the focused pane, ⌘T, ⌘⇧B and ⌘⇧G replace it with a terminal, browser or Changes pane. Anywhere else they behave as before.
- No duplicate header: a New Tab alone in its tab hides its pane header, since the tab already says "New Tab". In a split it keeps the header, so each pane can be told apart and closed. Splitting a lone New Tab is from the right-click menu. (
@superset/panesgets an optionalhideHeader(context)on pane definitions.) - Lists stay loaded:
useNewTabListsowns the pages and PR queries. The right pane area (mounted while the workspace is open) keeps them cached and refreshes them every minute, so a New Tab renders them on its first frame with no request. - One helper,
replaceNewTabPane, serves picks, page/PR clicks and hotkeys. It unpins first, because a header click pins a pane andreplacePaneskips pinned panes. @superset/panes:WorkspacetakesonAddTabso "+" can be a plain button. Newnew-tabpane kind.PagesListCardmoves up to be shared.EmptyTabActionButtontakes aclassName.- Removed
RightPaneAddMenu,RightPaneEmptyStateandpage.tsx'saddRightPane.
Choices to check
- PR +/− counts: the host's PR history doesn't store them, so each row reads them from the PR detail query the pull-request pane uses (local and cloud). The right pane area keeps those queries warm, so counts are there when a New Tab opens. A PR linked twice (for example under the old URL after the repo rename) shows once, keeping the newest link.
- Which pages: this workspace's pages, newest first. Sections with nothing to show are hidden.
- Terminal from the New Tab opens a blank terminal and skips "apply on new tab" presets, which build their own tab layout.
- Files, Review and Pages have no hotkeys. Split hotkeys still act on the center pane only.
Test cases
| Case | Expected | Checked |
|---|---|---|
| Open an empty right pane | One New Tab | App + hook test |
| Close the only tab / reopen | Pane closes, not refilled / fresh New Tab | App + hook test |
| "Move to Right Side" while closed | Only the moved pane | App |
| "+" | Adds a New Tab | App |
| "+" with the tab bar overflowing (2 → 15 tabs) | New tab fully visible every time | App + unit test |
| Split from header or context menu | New split is a New Tab | App + unit test |
| Lone New Tab / New Tab in a split | No header / header shown | App |
| Pick a tool (Browser, Files, Changes, Terminal) | Replaces in place, takes focus | App |
| Pick after a header click (pinned) | Still replaces | App + unit test |
| ⌘T / ⌘⇧B / ⌘⇧G with a New Tab focused | Replaces it in place, no extra tab | App |
| ⌘⇧B with another pane focused | Adds a browser tab as before | App |
| New Tab after 60 s with none on screen | Lists in the first render, 0 requests; background refresh ran once at 60 s | App |
| Click a page card / PR row | Page / PR pane in place of the New Tab | App |
| PR pane already open elsewhere | Retargets it, New Tab stays | Unit test |
| Desktop/Mobile tiles | Only on a sandbox / with mobile-pane | Unit test |
Known gap, not changed: "Reveal in sidebar" still targets the old sidebar's file tree, which the right pane area doesn't render.
Verification
- Dev app over CDP with
right-pane-areaon: every "App" row above, noconsole.error. A page opened from the New Tab gets the right page pane, but its body is blank locally becausebun devdoesn't run the page content server (port 6794). That applies to every page pane in this setup. bun test: new tests forreplaceNewTabPane,withNewTabSplits, the open-empty hook andcreateRightPanepass, pluspackages/panes. A full run of the v2-workspace folder shows 1 unrelated failure: a Lexical import-order error in the chat composer'suseLinkChips.test.tsx, which passes alone.- Biome clean.
typecheckhas no errors in changed files; the existing better-auth type errors inpackages/auth/packages/trpcare unrelated.check:i18nclean, no new strings.