cmux NEXT sidebar: multi-view prototype (navigate on release, drag without switching, on-screen rows lit)

Merged
TE
16d ago
+252-60

Leo's sidebar item D (2026-10-21) asked to "do the Claude Code desktop multi-view better". This PR is a prototype behind the Debug Settings toggle sidebar.multiView (Sidebar section, "Navigate on release (multi-view prototype)"), off by default. With the toggle off, nothing changes.

With it on:

  • A press doesn't navigate. Mouse-down on a workspace row changes nothing: no selection, no fill, no workspace switch. The release on the same row is the click that navigates. A press released over another row navigates nowhere.
  • Hold-then-drag keeps your place. Dragging a row moves it in the list, and the shown workspace and the selection stay as they were, in every frame and after the drop. Today a drag first selects and shows the row it lifts. A sideways drag out of the sidebar still hands off to the window drag, which already drops a workspace into a pane edge with a drop indicator (WorkspaceMerge).
  • Every workspace on screen is lit. SidebarModel.onScreen lists the workspaces the window has on screen. Their rows draw the multi-selection's soft fill (Palette.secondarySelectionFill), and the focused row keeps the selection's fill. A change to the set repaints only the row fills (syncRowStates), without a reload.

The Chrome, Claude desktop and Codex comparison is in cmuxterm-hq#2746 (knowledge/inspiration/sidebars.md).

Not built yet:

  • A window can show only one workspace's panes today, and no window view holds panes of several workspaces. So nothing sets onScreen in the App yet; the model and the drawing are here and tested.
  • A drop on a pane edge still merges the dragged workspace's tabs into the shown one, instead of placing the workspace beside it.
  • The view doesn't remember its workspaces yet (the implicit group).

These need the multi-workspace content view first; that is the next step.

SidebarModel's selection methods moved unchanged to SidebarModel+Selection.swift so the file shrinks instead of growing.

Changelog

none (Debug-only prototype, off by default)

Tests

SidebarMultiViewPressTests is the per-frame test. After each mouse event it lays the list out and draws a frame, then checks the selection, the shown workspace and the filled rows. The red commit has the toggle, the model field and the row state with no behavior.

  • Command: cmux-ci run --class light --script scripts/ci/package-test-lane.sh --arg=suite --arg=Packages/macOS/CmuxNext --arg=SidebarMultiViewPressTests --env CMUX_CI_XCODE_APP=/Applications/Xcode_26.6.app --ref <sha>
  • Red on c2b846862142 (step 9d244e3f3d9d57461a0596a1): 4 of 6 failed, 21 issues. Frame 0 (mouse-down) showed active=y where active=x was expected; the drag switched to the lifted row; no on-screen fills were drawn. The two toggle-off tests passed.
  • Green on 371e4d249870 (step for key smv-press5-after): 6 of 6 passed.
  • SidebarPointerGestureTests (the existing click, drag and stale-drag behavior, toggle off) on the same head: 9 of 9 passed.

The base's CmuxNext test target doesn't compile right now (#23363 isReadOnly, #23386 PaletteMenuVocabularyTests). Both fleet runs had those two one-line fixes on top, on scratch refs (scratch/smv-before, scratch/smv-after). This branch itself carries neither.

No capture: nothing visible changes with the Debug toggle off, which is the default. With it on, the App doesn't fill the on-screen set yet, so the press and drag behavior is proven by the per-frame test above.

Observed / Not run

  • Observed: the suites above on the fleet; scripts/cmux-next/prepush-gate.py (no new violations); the god-file check against base (SidebarModel.swift shrank from 615 to 564 lines).
  • Not run: a live app capture. The App doesn't set onScreen yet, so a capture would only show the press and drag behavior. No full CmuxNext suite.

🤖 Generated with Claude Code

Agent session: cosmic-gray