4.2 KiB
Explorer sidebar and side pane
The Explorer sidebar and the side pane share panel implementations, but they have different shell contracts.
| Surface | Purpose | Lifecycle |
|---|---|---|
| Explorer sidebar | Files and Changes navigation | Cmd+E shows or hides the dedicated dock |
| Side pane | Ordinary workspace content | Created and closed like any workspace pane |
Panel host contract
Every desktop panel registers its supported PaneHost values and presentation. Launchers derive
fixed-target labels and icons from that registration, filter by host, and never substitute one
panel type for another. Tab moves reject unsupported destinations, and placement resolves only to
a compatible pane.
Files and Changes are the Explorer defaults and its singleton navigation views. Other compatible
tabs, including agents, terminals, files, and diffs, can move between Explorer and main panes.
Keep panel implementations independent of either shell. WorkspacePanelHost owns mounting and
retention, while each shell owns its tabs, focus, dragging, resizing, and shortcuts.
Explorer sidebar
packages/app/src/workspace-tabs/explorer-sidebar.ts owns show, hide, toggle, and view selection.
On desktop, the shell is rendered outside the workspace split canvas so it divides the full
workspace, including the header. It has its own persisted width and resize handle. Main-pane splits
never read or modify that width.
The persisted layout still contains the Explorer pane so tabs survive reloads. The renderer removes
that pane from the workspace split tree and docks it separately. Persisted identifiers retain the
literal "explorer" pane id and explorerPaneIdByWorkspace key for compatibility.
The tab rail has no inline add or close controls. Its context menu opens a New Tab launcher and toggles the singleton Files and Changes views. Individual tab menus close instances or move compatible tabs to main. Explorer tabs can be reordered, but the dock cannot be split. Selecting an Explorer tab does not change workspace focus.
Cmd+E selects Changes for Git workspaces and Files otherwise. Compact layouts use the combined full-screen Explorer overlay and close it after a file opens. Wide native layouts without pane splits use the same combined content in a resizable inline dock; opening a file leaves that dock visible. Both presentations keep their selection in the panel store and reuse the layout store's per-workspace Explorer width. They do not create a second Explorer lifecycle.
Side pane
packages/app/src/workspace-tabs/open-beside.ts owns content opened beside the user's work. The
layout store remembers one ordinary pane per workspace. The first side open creates a full-height
right split around the workspace root; later side opens reuse it.
Closing the pane or moving away its final tab removes it normally and clears the remembered id. A later side open creates a new pane. There is no hidden side-pane lifecycle.
Placement intent still controls existing tabs:
| Mode | New target | Existing target |
|---|---|---|
pane |
opens in the requested pane | moves to the requested pane |
prefer |
opens in the requested pane | stays where the user placed it |
focused |
opens in the focused pane | focuses it where it already lives |
ambient |
opens in a compatible pane | focuses it where it already lives |
Explicit Open to Side uses pane. Implicit opens use prefer, so a preference affects only a
new target and never yanks an existing tab out of a user-selected pane.
Routing preferences
Desktop Settings → Layout → Open in side pane has independent switches for Explorer Files, Explorer Changes, chat files, diff files, subagents, pull requests, and Changes links. All switches default off. Mobile ignores them.
Panels request an implicit open through the narrow openPreferredTarget(target, source) pane
contract. Entry points outside panels use openPreferredWorkspaceTarget. Do not branch on a
specific shell inside a panel.