feat(sidebar): add workspace sections with drag & drop reordering
Merged
JI
8mo ago+3548+3548+0123456789012345678901234567890123456789-284-284-012345678901234567890123456789
Demo
Sections
https://www.youtube.com/watch?v=qzNTkqexMSw
Multi-Select & Batch Move
https://www.youtube.com/shorts/HZz8ifI8mJc
Summary
- Add workspace sections: user-created groups within a project sidebar for organizing workspaces
- Support full drag & drop: reorder workspaces within sections, move between sections, and reorder sections themselves
- Multi-select workspaces with Cmd+click (toggle) and Shift+click (range), then drag or context-menu move as a batch
- New
workspace_sectionstable in local SQLite DB with Drizzle migration
Why / Context
As the number of workspaces per project grows, the flat list becomes hard to manage. Sections let users group related workspaces (e.g., by feature, sprint, or status) with collapsible headers and drag-and-drop reordering.
How It Works
Data layer:
- New
workspace_sectionstable (id,projectId,name,tabOrder,isCollapsed) workspaces.sectionIdFK (nullable,onDelete: set null) — ungrouped workspaces remain at the top- 7 new tRPC mutations: create/rename/delete section, toggle collapse, reorder sections, reorder workspaces within section, move workspace to section
moveWorkspacesToSectionbatch mutation for moving multiple workspaces at once (singleinArrayUPDATE)
UI layer:
WorkspaceSectioncomponent: collapsible header with context menu (rename, delete), section-level DnD viareact-dndWorkspaceListextracted as shared list renderer for both ungrouped and sectioned workspacesuseSectionDropZonehook: native drag event handling for cross-section workspace moves with 600ms auto-expand on collapsed sectionsactive-drag-itemZustand store: bridgesreact-dnddrag state with native drop zone handlersworkspace-selectionZustand store: tracks multi-select state (Cmd+click to toggle, Shift+click to range-select)MultiDragPreviewcustom drag layer showing "{N} workspaces" badge during multi-drag- "Move to Section" context menu on workspace items (batch-aware when multiple are selected)
getAllGroupedquery now returns sections nested under each project
Manual QA Checklist
Section CRUD
- Right-click project header → "New Section" creates a section
- Right-click section header → "Rename Section" works
- Double-click section header enters rename mode
- Right-click section header → "Delete Section" removes it (workspaces return to ungrouped)
- Section collapse/expand toggles persist after app restart
Multi-Select
- Cmd+click toggles individual workspace selection (highlighted with ring)
- Shift+click selects a range of workspaces (across sections within same project)
- Cmd+click on a workspace in a different project resets selection to that project
- Escape clears selection
- Clicking empty sidebar space clears selection
- Plain click navigates and clears selection
Drag & Drop — Workspaces
- Drag workspace within a section to reorder
- Drag workspace from ungrouped area into a section
- Drag workspace from one section to another
- Drag workspace out of a section to ungrouped area
- Hovering over collapsed section auto-expands it after ~600ms
- Multi-select then drag moves all selected workspaces to the target section
- Multi-drag shows "{N} workspaces" badge and dims selected items
Drag & Drop — Sections
- Drag section header to reorder sections within a project
- Section reorder persists after app restart
Context Menu
- Right-click workspace → "Move to Section" submenu shows all sections
- Moving via context menu works correctly
- Right-click with multi-selection → "Move to Section" moves all selected workspaces
Edge Cases
- Empty sections render correctly
- Sidebar collapsed mode still shows workspaces (sections hidden)
- Keyboard shortcuts (Cmd+1-9) still work across sections
Testing
bun run typecheck— passes (pre-existing@ai-sdk/openaierror on upstream, unrelated)bun run lint:fix— passes
Known Limitations
- No search/filter within sections
- Section names are not validated for uniqueness within a project
- Reorder operations update all
tabOrdervalues in a loop (fine for typical section/workspace counts, not optimized for hundreds)
Follow-ups
- Drag workspace to create a new section (auto-group)
- Section color/icon customization
- Persist section collapsed state per-device sync