A modular layout system enabling N user-generated canvases with N custom panels.
app.tsx
└─ <CanvasRenderer> # Single entry point for all canvases
└─ <Canvas> # Renders columns based on config
└─ <Column> # Sizing, resize, drag-and-drop
└─ Panel # PRList, BranchList, GitGraph, etc.
| Component | Purpose |
|---|---|
CanvasRenderer.tsx |
Main entry point - data/handlers → panels |
CanvasContext.tsx |
Global state, reducer, presets |
Canvas.tsx |
Column layout, visibility, drag state |
Column.tsx |
Width, resize, drag-and-drop |
EditorSlot.tsx |
Editor panel with back/forward nav |
| Component | Purpose |
|---|---|
PRList.tsx |
Pull requests with search/filter/sort |
BranchList.tsx |
Local/remote branches |
WorktreeList.tsx |
Worktrees with parent filtering |
StashList.tsx |
Stash entries |
CommitList.tsx |
Commit history list |
RepoList.tsx |
Multi-repo selector |
Sidebar.tsx |
All items in collapsible sections |
ListPanelHeader.tsx |
Shared header component |
| Component | Purpose |
|---|---|
GitGraph.tsx |
Git commit graph with lanes |
ContributorChart.tsx |
Contributor activity over time |
TechTreeChart.tsx |
Merged branches visualization |
RADAR_CANVAS // 5 list columns + hidden editor: stashes, prs, worktrees, branches, remotes
FOCUS_CANVAS // sidebar + git-graph + editor
GRAPH_CANVAS // git-graph only (full width)interface Column {
id: string
slotType: 'list' | 'editor' | 'viz'
panel: PanelType
width: number | 'flex'
minWidth?: number
label?: string
icon?: string
visible?: boolean
collapsible?: boolean
}
interface Canvas {
id: string
name: string
columns: Column[]
isPreset?: boolean
icon?: string
}- Create preset in
CanvasContext.tsx:
export const MY_CANVAS: Canvas = {
id: 'my-canvas',
name: 'My Canvas',
icon: '🔮',
isPreset: true,
columns: [
{ id: 'col-1', slotType: 'list', panel: 'pr-list', width: 'flex' },
],
}-
Add to
PRESET_CANVASES -
Add tab button in header (app.tsx)
-
Create component in
app/components/panels/list/orviz/ -
Add to
CanvasRenderer.tsx:
case 'my-panel':
return <MyPanel column={column} ... />- Add type to
app-types.ts
CanvasContext (global state)
↓ dispatch actions
canvasReducer
↓ updates
activeCanvas, editorState
↓ consumed by
CanvasRenderer
↓ renders
Panels
app/components/
├── canvas/
│ ├── Canvas.tsx # Column layout container
│ ├── CanvasContext.tsx # State, reducer, presets
│ ├── CanvasRenderer.tsx # Main entry point
│ ├── Column.tsx # Width, resize, drag
│ └── EditorSlot.tsx # Editor with navigation
└── panels/
├── list/
│ ├── PRList.tsx
│ ├── BranchList.tsx
│ ├── WorktreeList.tsx
│ ├── StashList.tsx
│ └── Sidebar.tsx # Focus mode sidebar
├── viz/
│ └── GitGraph.tsx
└── editor/
└── ... # Detail panels