mirror of
https://github.com/getpaseo/paseo.git
synced 2026-10-23 09:42:53 +00:00
* Stack workspace sheets and tighten sidebar density - Workspace sheets stack: opening a target from a sheet covers it, Back and drag close only the top sheet, and the header is the sheet's drag handle. - The workspace sheet reuses the shared sheet handle, background and header. - Fix the shared sheet handle indicator rendering black. - Sidebar text returns to semantic sizes; Pinned and Workspaces share one section header. * Pause covered workspace sheets and mock the shared sheet handle in tests * Export BottomSheetHandle from the browser test Gorhom stub * Let a stacked sheet's backdrop catch taps on iOS * Bring a revealed sheet to the top instead of duplicating it as a tab
124 lines
8.0 KiB
Markdown
124 lines
8.0 KiB
Markdown
# 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 |
|
||
| Workspace sheet | Compact look-ups | Stacks tabs; each closes or becomes a tab |
|
||
|
||
## 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. Their panel manifests mark them as singletons,
|
||
so a pane’s + menu omits each while that pane already contains it. Closing one makes its menu
|
||
item available again. 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.
|
||
|
||
## Workspace sheet
|
||
|
||
On compact layouts, files and subagents open in a closable sheet over the workspace, so the tab
|
||
switcher keeps only agents and terminals. A panel kind opts in with `compactSheet` in its manifest
|
||
(`packages/app/src/panels/panel-manifest.ts`), and the layout store's `openTab` decides between
|
||
sheet and tab, so callers open targets the same way on every layout. Each sheet holds one ordinary
|
||
`WorkspaceTab`, and sheets stack: a target opened from a sheet covers it, and closing the top sheet
|
||
(drag, Close, backdrop, or Android Back) uncovers the one below. Revealing a target that already has
|
||
a sheet brings that sheet back to the top and closes the sheets above it, except ones holding unsaved
|
||
work. Opening a sheet as a tab dismisses the sheets above it, since the
|
||
tab would sit under them. The stack is not persisted.
|
||
|
||
Sheets are modal and cover the whole compact column, header included. A sheet's header is its drag
|
||
handle, because the panel scrolls on its own and content panning would fight it. Sheets render in
|
||
the workspace tree rather than through `IsolatedBottomSheetModal`: their panels need the navigator
|
||
and every workspace provider an ordinary pane has, and a portal drops them
|
||
([floating-panels.md Gotcha 7](floating-panels.md#gotcha-7--a-sheet-cannot-read-context-from-its-call-site)).
|
||
|
||
A sheet holding unsaved work is never implicitly displaced; only its guarded close removes it.
|
||
Moving its tab to another host remounts the panel, and the file editor keeps unsaved text in the
|
||
mounted view, so the move would drop it. Widening the layout is the known exception: it still moves
|
||
the sheet's tab into a pane, and edits the autosave has not started writing are lost.
|
||
|
||
## 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.
|
||
|
||
`packages/app/src/workspace-tabs/open-supporting-view.ts` owns semantic Changes and pull-request
|
||
opens. Compact and wide native layouts select the matching Explorer tab. Desktop Changes opens
|
||
follow the shared diff preference. Desktop pull requests use their Main panel, On the side, or
|
||
Explorer sidebar setting. Automatic PR discovery follows that preference once per workspace without
|
||
interrupting the user's work. Closing the tab opts that workspace out of future automatic opens,
|
||
even for a different PR; moving or reordering it remains the user's choice.
|
||
Callers request the content and never choose the shell.
|
||
The composer Changes pill is a two-stage desktop action: it first reveals Explorer on Changes, then
|
||
routes later presses to the working diff through the shared diff preference.
|
||
|
||
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.
|
||
|
||
Explorer uses the shared workspace tab row and ordinary tab context menus. Files and Changes
|
||
hide their close buttons through the panel manifest; close them from the tab context menu.
|
||
Other tabs reveal the close control on hover. The + menu opens compatible panels in the dock and
|
||
omits Agent and terminal profiles. Agents and terminals can still be dragged into Explorer.
|
||
Bulk-close actions apply only to the dock's tabs. Explorer tabs can be reordered and dragged
|
||
between compatible panes, but the dock cannot be split or maximized. Selecting an Explorer tab
|
||
does not change workspace focus.
|
||
|
||
Cmd+E shows or hides Explorer without changing its selected view. Compact layouts use the combined
|
||
full-screen Explorer overlay for Changes, Files, and pull requests, and close it after a file opens. Compact Changes has no tree rail; its overview is the Jump to file action (`packages/app/src/git/jump-to-file/`), a sheet over the same changed-files tree the desktop rail renders.
|
||
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. Only the `split-panes` layout
|
||
mode opens beside. Compact and single-pane layouts (touch tablets) open the same target in the main
|
||
pane, so callers never check whether splits render.
|
||
|
||
Removing a pane clears its remembered id; a later side open creates a new pane. The last visible
|
||
ordinary pane stays when its final tab closes and shows the New launcher. An empty workspace does
|
||
not automatically create an agent draft tab; choosing Agent opens one. Explorer cannot replace the
|
||
workspace canvas, even when visible. Restoring a saved layout enforces the same rule while preserving Explorer and saved
|
||
tab content. 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 location** has independent Main panel or On the side choices for
|
||
Explorer Files, diffs, chat files, files opened from diffs, and subagents. They default to Main
|
||
panel. Mobile ignores them.
|
||
|
||
Pull requests have a three-way open location: Main panel, On the side, or Explorer sidebar. Explorer
|
||
sidebar is the default. Compact layouts always open pull requests in Explorer regardless of this
|
||
desktop preference.
|
||
|
||
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.
|