Skip to content

feat(desktop): right pane file tabs with preview and pinned states - #8964

Merged
saddlepaddle merged 24 commits into
mainfrom
saddlepaddle/right-pane-files-ux-like-cursor-chatgpt
Oct 28, 2026
Merged

saddlepaddle merged 24 commits into
mainfrom
saddlepaddle/right-pane-files-ux-like-cursor-chatgpt

Conversation

@saddlepaddle

@saddlepaddle saddlepaddle commented Oct 27, 2026 •

Copy link
Copy Markdown
Collaborator

What

Files in the right pane open as tabs in the right pane's tab bar, using the preview/pin model editors use. All of it is behind the right-pane-area flag, except the file header change noted below.

Opening and pinning

  • Click a file in the tree: it opens in the preview tab (italic title). The next click on another file replaces it in place.
  • Click an open file again in the tree: pins it.
  • Double-click a file in the tree: renames it, as in the sidebar.
  • Click the preview's tab once: pins it.
  • Click inside the file view or edit the file: pins it.
  • Quick open (⌘P) opens files pinned.
  • Right pane tabs can't be renamed (no double-click rename, no Rename in the menu).

File view layout (the pane header stays the standard one)

  • Breadcrumb chip floats at the top left of the content, with the file icon and an unsaved dot.
    • It shows as many crumbs as fit, keeping 64px clear of the buttons on the right; the rest collapse into "…".
    • Clicking a crumb opens a popover tree of that folder. Clicking "…" lists the hidden folders; picking one shows its tree.
    • The unsaved dot and Save keep their space while hidden, so editing doesn't change the crumbs.
  • Floating buttons at the top right, in the same spot whether the tree shows or not: Save (filled, only while there are unsaved changes), Open in for the file, and the tree toggle.
  • Tree below the buttons, flush to the right and bottom edges, with a rounded top-left corner.
    • Resizable; double-click the divider to reset the width. Dragging it closed turns the toggle off.
    • Opens and closes with a 200ms animation.
    • Row on top: "Search files" (opens quick open), New File, New Folder, Refresh, Collapse all. Right-click empty space for New File / New Folder at the root.
  • Repo picker above the tree, hidden unless the workspace has 2+ repos. For now the host returns only the primary repo, so it never shows (see How).
  • "Files" with no file open shows an empty section next to the tree.

File header change everywhere (flag off too)

  • Copy path, Reveal in Finder and Open in editor are replaced by the existing Open in split button, used for the file. Its menu has the editors, Finder and Copy path. Cloud workspaces keep a plain Copy path button.
  • Save shows only while the file has unsaved changes.
  • In the right pane, Save and the unsaved dot live in the content, not the header or tab.

Screenshots at this head: to follow.

How

  • @superset/panes Workspace options: renameTabs (off in the right pane), onTabClick (runs after select; the right pane pins preview tabs with it), isPreviewTab (italic title). The center pane is unchanged.
  • openFileFromTree (9 tests) holds the tree rules: pin an already open file; turn the empty Files view into the file; replace the preview; otherwise add a tab.
  • FileViewLayout wraps file panes in the right pane store: breadcrumb, floating buttons, and a collapsible ResizablePanelGroup for the tree. Old saved layouts with a separate Files pane still render; the file view hides its own tree there.
  • New host-service procedure workspace.repositories (additive, 3 tests) returns { id, path, name, primary }[], one primary repo for now, named after its checkout folder. The picker treats an error from an older host as "one repo". Multi-repo comes later with a host workspace_repositories table (FK to workspaces) that replaces the hidden sibling workspace rows cloud boxes use today.
  • V2OpenInMenuButton takes path and an optional branch, and a hotkeys option so per-file buttons don't bind the workspace hotkeys.

Notes

  • Tree search opens quick open. Filtering in place would only see folders already loaded, since the tree loads lazily.
  • Tree width and the toggle are in memory and reset on restart (no localStorage).
  • Each file tab has its own tree, so switching tabs resets scroll and open folders; the current file is revealed.
  • Pierre trees has no empty-space context menu, so the root New File / New Folder menu is ours. A beta.6 bump is a separate PR.

Verification

  • Tests: openFileFromTree 9 cases; workspace.repositories 3 cases; panes 140 pass; host-service workspace router 336 pass, plus the snapshot-field guard. Full desktop suite: 8795 pass, 38 fail, all in git/shell main-process tests this PR doesn't touch, failing with posix_spawn EAGAIN while the dev app ran; one of those files passes alone.
  • Checks: Biome and check:i18n clean. Typecheck shows only the existing auth typing errors in packages/auth / packages/trpc.
  • In the dev app over CDP (flag on):
    • one click on an open preview in the tree pins it;
    • one click on a preview tab pins it;
    • divider double-click resets the tree width;
    • long paths collapse into "…", crumb popovers open their folder, "…" lists the hidden trail;
    • toggling the tree leaves the breadcrumb in place while the tree animates (sampled per frame).
  • Not yet clicked through: root empty-space menu, tree highlight of the open file, double-click rename in the right pane tree, cloud workspace Copy path fallback, an older host without workspace.repositories.

@coderabbitai

coderabbitai Bot commented Oct 27, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

Caution

Review failed

The pull request is closed.

Finishing Touches
📝 Generate docstrings
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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.

@github-actions

github-actions Bot commented Oct 27, 2026 •

Copy link
Copy Markdown
Contributor

🧹 Preview Cleanup Complete

The following preview resources have been cleaned up:

  • ✅ Neon database branch

Thank you for your contribution! 🎉

@saddlepaddle saddlepaddle changed the title feat(desktop): file tabs with preview and pinned states in the right pane Files tab feat(desktop): right pane file tabs with preview and pinned states Oct 28, 2026
…pane Files tab

The Files tab now shows a code area with a tab strip next to the tree.
A single click opens a file in the preview tab (italic), which the next
single click replaces. Double-clicking the file or its tab, or editing
it, pins the tab so it stays open.

Open files stay real panes. The panes store can now keep panes in a
tab but out of its layout: stackPane shows a new pane in another
pane's slot, activating a stacked pane swaps it into view, and closing
or moving the visible one hands its slot to its nearest stacked
sibling instead of collapsing the split. Close guards, pane reuse and
persisted layouts keep working as before.
Files open as tabs in the right pane's tab bar. A single click on a
file in the tree opens it in the preview tab (italic title), which the
next single click replaces. A file pins when you double-click it in
the tree, double-click its tab, click inside its view, or edit it.
Clicking an open file again only switches to it. Quick open pins.

Each file view keeps the standard pane header. The tree sits inside
the view with a toggle in the header, and a breadcrumb chip floats
over the code. "Files" opens the same view with no file yet.

Right pane tabs can no longer be renamed; a double-click pins
instead. The file header drops its always-on Save, Copy path, Reveal
and Open in editor buttons for Save while unsaved and the Open in menu.

The panes package gains Workspace options for this (renameTabs,
onTabDoubleClick, isPreviewTab). The stacked-panes store change from
the first commit is reverted.
Pinning a right-pane preview tab took a double-click. Workspace's
onTabDoubleClick becomes onTabClick, which runs after the click selects the
tab; the right pane pins the tab's preview panes there. A drag never fires a
click, so reordering a preview tab leaves it a preview.
The tree only moved keyboard focus to the open file, and only when its row
was already loaded, so the row matching the tab was never shown selected.
It now reveals the open file the way Reveal in sidebar does: expand its
folders, select only its row and scroll it into view, each time the open
file changes.
A file or folder deleted from the Files tree now closes every file pane
showing it, or anything under it, in both pane areas. Deletes from outside
the app keep the 'File was deleted on disk' banner, so unsaved edits are
not thrown away.
The tree inside a right pane file view keeps its own row: search (an
icon), Refresh and Collapse all, then Open in and the tree toggle. New
File and New Folder come from the context menu; right-clicking empty
tree space offers them for the project root. With the tree hidden, Open
in and the toggle sit in the pane header.
… toggle

With the tree hidden, the right pane file view shows a small floating
pill at its top right (Open in, search, show tree) where the tree's row
was, instead of moving those into the pane header.
Shows the workspace's repo in a dropdown at the top of the tree. It lists
only the primary repo for now; multi-repo workspaces follow.
…resizable

Open in and the tree toggle float at the file view's top right and stay
put whether the tree shows or not. The tree keeps its own search, Refresh
and Collapse all, sits flush against the pane edge, and its width is
resizable. The view stays mounted when the tree toggles.
…ed corner

The resizable tree starts under Open in and the tree toggle, flush with
the pane's right and bottom edges, with a rounded top-left corner. The
resize handle is the card's left edge.
…iew's tree

Pierre opens a context menu only on rows, and a large repo's tree has no
empty space to right-click, so the root needs its own buttons.
…ker hides with one repo

host-service gains workspace.repositories, the shape multi-repo
workspaces will return; for now it lists the workspace's one repository.
The file view's repo picker shows only for two or more, and hides the same
way on a host without the procedure.
A tab click pins only a preview tab, so browser and other unpinned
panes keep being reused. Opening a file in a new tab from the tree goes
through openFileFromTree, so an open file is focused instead of
duplicated. The tree toggle moves under its one user.
… renames

A click opens a file as the preview, a second click on it pins it, and
a double-click renames it, as in the sidebar tree. The tree's
double-click-to-pin override is gone.
… its content

In the right pane, the unsaved dot moves into the breadcrumb next to the
file name and Save floats with Open in, instead of both sitting in the
pane header. Other file panes keep them in the header.
The file view's breadcrumb shows as many trailing crumbs as fit before
the floating actions (keeping 64px clear) and folds the rest into an
ellipsis. Clicking a crumb opens its parent folder as a small tree, with
the path to the current file expanded and the file highlighted; picking
a file opens it as the preview.
Clicking the ellipsis shows the folders it folds away, top to bottom;
picking one opens that folder's level as a tree, like its crumb would.
The breadcrumb renders beside the floating actions instead of inside the
code panel, so how many crumbs fit depends only on those actions and
toggling the tree no longer changes it. The tree panel stays mounted and
collapses or expands with a short width transition; dragging it closed
also hides it.
The dirty dot and the Save button keep their space while hidden, so the
breadcrumb fits the same number of crumbs before and after an edit.
…eckout folder

Reading project.repoName tripped the guard that keeps cached GitHub
snapshot fields out of host-service queries.
@saddlepaddle
saddlepaddle marked this pull request as ready for review October 28, 2026 18:43
@saddlepaddle
saddlepaddle merged commit 55a1e1d into main Oct 28, 2026
21 checks passed
@greptile-apps

greptile-apps Bot commented Oct 28, 2026 •

Copy link
Copy Markdown
Contributor

RetriggerView in GreptileConfidence Score: 4/5

[Medium impact] The main reach is the desktop workspace’s right-pane file workflow.

Fix the missing file controls in saved split layouts before merging.

Findings

  1. P1 Saved layouts lose file controls ▶
  2. P2 Root menu uses selected folder ▶
  3. P2 Outside files show wrong folders ▶
Fix with agent prompt
### Issue 1
apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/usePaneRegistry/components/FileViewLayout/FileViewLayout.tsx:55-58
For a restored right-pane tab containing both `files` and `file` panes, this return removes the breadcrumb and floating buttons. `FilePaneHeaderExtras` also hides Save and Open in for right-pane files, while `showDirty` hides the header dot. The file therefore has no Save button, Open in menu, or visible unsaved marker. Skip only the duplicate tree, not the file controls.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

### Issue 2
apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/components/WorkspaceSidebar/components/FilesTab/FilesTab.tsx:451-458
After a user selects a nested folder or file, right-clicking blank space leaves that selection intact. These calls omit the parent, so `startCreating` uses the selected folder or the selected file's parent instead of the workspace root. The new item appears in the wrong directory. Pass `rootPath` explicitly to both root-menu actions.

### Issue 3
apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/usePaneRegistry/components/FileViewLayout/components/FileBreadcrumb/FileBreadcrumb.tsx:41-47
Terminal file links can open absolute paths outside the checkout. `toRelativeWorkspacePath` returns those paths unchanged, but this code still prepends `rootPath`. With root `/repo` and file `/tmp/example.txt`, the file's breadcrumb menu lists `/repo/tmp` instead of `/tmp`. Users see the wrong folder or an empty list. Build the trail from the absolute path when the file is outside the workspace.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Summary

Adds preview and pinned file tabs in the right pane.

  • Right-pane files open in preview tabs that can be pinned.
  • The right-pane file view keeps a tree and path controls beside the file.
  • File actions now use one Open in menu for local files.
  • Deleting files closes their open file panes.
  • The host reports a workspace’s primary repository for the tree picker.

A saved split layout can lose its file controls and unsaved marker. Two smaller issues affect root-menu creation and breadcrumbs for files outside the checkout.

Diagram

%%{init: {'theme': 'neutral'}}%%
flowchart TD
  A[Tree or breadcrumb file click] --> B{File already open?}
  B -->|Yes| C[Select and pin file]
  B -->|No| D{Empty Files pane?}
  D -->|Yes| E[Replace Files pane]
  D -->|No| F{Preview exists?}
  F -->|Yes| G[Replace preview path]
  F -->|No| H[Add preview tab]
  I[Quick open] --> J[Open file and pin it]
  E --> K[File view]
  G --> K
  H --> K
  K --> L[Breadcrumb and floating buttons]
  K --> M[Collapsible file tree]
Loading

Reviews (1) · Last reviewed commit: "fix(host-service): workspace.repositorie..." · Reviewed by Greptile

Comment on lines +55 to +58
const tabHasTreePane =
context.pane.kind !== "files" &&
Object.values(context.tab.panes).some((pane) => pane.kind === "files");
if (!showTree || tabHasTreePane) return children;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P1 Saved layouts lose file controls

For a restored right-pane tab containing both files and file panes, this return removes the breadcrumb and floating buttons. FilePaneHeaderExtras also hides Save and Open in for right-pane files, while showDirty hides the header dot. The file therefore has no Save button, Open in menu, or visible unsaved marker. Skip only the duplicate tree, not the file controls.

Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/usePaneRegistry/components/FileViewLayout/FileViewLayout.tsx
Line: 55-58

Comment:
**Saved layouts lose file controls**

For a restored right-pane tab containing both `files` and `file` panes, this return removes the breadcrumb and floating buttons. `FilePaneHeaderExtras` also hides Save and Open in for right-pane files, while `showDirty` hides the header dot. The file therefore has no Save button, Open in menu, or visible unsaved marker. Skip only the duplicate tree, not the file controls.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Comment on lines +451 to +458
<DropdownMenuItem
onSelect={() => setTimeout(() => void startCreating("file"), 0)}
>
<FilePlus />
<Trans>New File...</Trans>
</DropdownMenuItem>
<DropdownMenuItem
onSelect={() => setTimeout(() => void startCreating("folder"), 0)}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2 Root menu uses selected folder

After a user selects a nested folder or file, right-clicking blank space leaves that selection intact. These calls omit the parent, so startCreating uses the selected folder or the selected file's parent instead of the workspace root. The new item appears in the wrong directory. Pass rootPath explicitly to both root-menu actions.

Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/components/WorkspaceSidebar/components/FilesTab/FilesTab.tsx
Line: 451-458

Comment:
**Root menu uses selected folder**

After a user selects a nested folder or file, right-clicking blank space leaves that selection intact. These calls omit the parent, so `startCreating` uses the selected folder or the selected file's parent instead of the workspace root. The new item appears in the wrong directory. Pass `rootPath` explicitly to both root-menu actions.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Comment on lines +41 to +47
const relativePath = rootPath
? toRelativeWorkspacePath(rootPath, filePath)
: filePath;
const segments = relativePath.split(/[\\/]/).filter(Boolean);
const base = rootPath?.replace(/[\\/]+$/, "") ?? "";
const pathOf = (count: number) =>
[base, ...segments.slice(0, count)].join("/") || "/";

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2 Outside files show wrong folders

Terminal file links can open absolute paths outside the checkout. toRelativeWorkspacePath returns those paths unchanged, but this code still prepends rootPath. With root /repo and file /tmp/example.txt, the file's breadcrumb menu lists /repo/tmp instead of /tmp. Users see the wrong folder or an empty list. Build the trail from the absolute path when the file is outside the workspace.

Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/hooks/usePaneRegistry/components/FileViewLayout/components/FileBreadcrumb/FileBreadcrumb.tsx
Line: 41-47

Comment:
**Outside files show wrong folders**

Terminal file links can open absolute paths outside the checkout. `toRelativeWorkspacePath` returns those paths unchanged, but this code still prepends `rootPath`. With root `/repo` and file `/tmp/example.txt`, the file's breadcrumb menu lists `/repo/tmp` instead of `/tmp`. Users see the wrong folder or an empty list. Build the trail from the absolute path when the file is outside the workspace.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

This branch was previously deployed

1 inactive deployment
preview — e5bfa862 Deployed Oct 28, 2026 by saddlepaddle via Deploy Docs #13065
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