cmux-next: custom workspace sidebar (groups, machines, drag, tab drop)
Summary
CmuxNextSidebar: a fully custom, layer-backed AppKit sidebar (no NSOutlineView/NSTableView/SwiftUI List). Machine sections (local, Cloud VMs), a pinned area, collapsible colored workspace groups, drag reorder with a lifted glass row and springs, an external tab-drop API with spring-loading, icons-only and hidden modes, live density tokens.
- Model:
@Observable @MainActor SidebarModel(sections -> groups -> workspaces, selection, filter, presentation, width) andSidebarIntentout (select,reorder(ids, to:),move(ids, toGroup:),reorderGroup,createGroup,renameGroup,setGroupColor,setGroupPinned,closeGroup,openGroup,ungroup,toggleCollapse,close,rename,setColor,setIcon,setPinned,newWorkspace). WithoutonIntentthe model applies intents locally (mock and optimistic updates). - Pure logic with tests:
SidebarLayout(flattening, per-row heights, live gap, O(1) key index, binary-search hit test),DropResolver(drop math in post-removal coordinates, gap feedback cancelled),KeyboardReorder(Cmd-Opt-Up/Down slots),SidebarEdits(tree edits),resolveTabDrop(external tab drag). - Views: only rows near the viewport have views (reuse pool), selection pill and drag gap are CALayers with CA springs, manual frame layout, no NSHostingView. Right-click goes through
contextMenuProvider(App builds menus from the action registry). SidebarContainerViewowns the glass panel, width constraint, and resize handle.SidebarMock.makeModel()(40 workspaces, 2 machines) andmakeLargeModel(count:).- Package.swift: adds
resources: [.process("Resources")]to the CmuxNextSidebar target for its Localizable.xcstrings (en, ja).
Testing
swift build --build-testsandswift test --filter CmuxNextSidebarTests(56 tests) in Packages/macOS/CmuxNext.scripts/cmux-next/check-no-godfiles.shpasses for the module.- Throwaway demo executable driven by synthesized mouse events: single and multi-row drag, drop into group, cancel, tab-drop gap and spring-load, icons-only, comfortable density, filter. Screenshots were checked; not attached.
- 1000 workspaces (release): full layout 0.14 ms, steady reload 0.5 ms, about 55 row views alive.
Changelog
none
🤖 Generated with Claude Code
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.
Summary by cubic
Builds a fully custom AppKit sidebar for cmux-next, replacing the placeholder. It adds machine sections, a pinned area, collapsible colored workspace groups, spring-animated drag reorder, and an external tab-drop API with icons-only and hidden modes following live density tokens.
New Features
- Layer-backed custom list (no NSOutlineView/NSTableView/List); only rows near the viewport get views, recycled through a per-class pool.
@Observable SidebarModelemitsSidebarIntents; setonIntentto forward them to the daemon, otherwise they apply locally (optimistic).- External tab drags call
SidebarView.externalDragMoved, which returns a proposal and highlight rect, opens a gap, and spring-loads workspace rows after a hover delay. - Adds 56 tests covering reorder, drop resolution, keyboard reorder, tab drops, and group verbs.