Skip to content

feat(THI-246 PR 1/3): Split layout foundation — switcher + skeleton - #113

Merged
tdody merged 2 commits into
mainfrom
thibaultdody/thi-246-split-foundation
Jun 7, 2026
Merged

feat(THI-246 PR 1/3): Split layout foundation — switcher + skeleton#113
tdody merged 2 commits into
mainfrom
thibaultdody/thi-246-split-foundation

Conversation

@tdody

@tdody tdody commented Jun 7, 2026

Copy link
Copy Markdown
Owner

Summary

First of three PRs that ship the Split view (v0.3 Track 3). THI-246 is explicitly L-sized — 4 new components, drag-to-reorder, xterm reconnect logic, multiple new state pieces, a 600+ LOC prototype to recreate. Splitting it across 3 PRs so each one is reviewable and ships incrementally:

  • PR 1 (this PR): Foundation. Layout choice exists end-to-end; click-to-select persistence works; rail and detail are skeletons.
  • PR 2: Rail features — repo-grouped tree (consumes THI-243), collapse, divider resize, drag-to-reorder, "+ New tab" rows.
  • PR 3: Detail pane — inline xterm with reconnect-don't-recreate, header chips, sidebar (Linked / Notes / Activity).

What ships in PR 1

Types + setting

  • Layout union extended: "kanban" | "grid" | "list" | "split". Updates every enumeration site.
  • New selectedPaneId: string setting (default ""). Restored on reload + layout swap.
  • New splitRailWidth: number setting (default 280). Divider drag (PR 2) will clamp to 200–460.

UI surface

  • New "split" glyph in Icon.tsx — rail + detail rectangles, stroke-matched to the other layout glyphs.
  • 4th LayoutSwitcher button in Subhead: Kanban · Grid · List · Split.
  • New components/split/SplitView.tsx (~180 LOC): CSS grid <railWidth>px 7px 1fr filling .main.
    • Rail: PR-1 flat Session → Pane tree (mirroring Kanban's sortPendingFirst order). PR 2 swaps this to the Repo → Worktree → Pane tree from THI-243's discovery feed.
    • Detail: placeholder showing the selected pane's name, session, branch, status, plus a focus-in-tmux button. Empty-state hint when no pane is selected.
  • App.tsx branches on layout === "split" → renders <SplitView>. Other views unchanged.
  • suggestLayout never auto-suggests Split (opt-in, same as Grid).

Styles

  • New .sb-* CSS block (~180 lines) using only existing tokens (--bg-elev, --hairline, --text-mute, --accent-soft, etc.). PR 1 styles only what PR 1 renders; PR 2 + PR 3 add their pieces.

Tests

  • 6 new tests for SplitView: empty-state, row rendering, click-to-select persistence, mount-time restore, rail-width plumbing, focus-in-tmux callback.
  • 2 new settings.test.ts cases for the two new fields.
  • Updated Subhead layout-switcher test for the 4-button count.

Test plan (automated)

  • Full frontend: 557 tests pass (npm test).
  • npm run typecheck: clean.
  • npm run build: clean.

Manual smoke (needs a live session — only the user can run this)

Switcher + skeleton

  • Subhead's layout switcher now has 4 buttons: Kanban / Grid / List / Split. Tooltips show on hover.
  • Click the Split button. The icon highlights; the main area swaps to a rail + divider + detail layout.
  • The rail lists every visible session, with each session's windows nested under a header row.
  • No pane is selected by default — the detail pane shows "Select a pane from the rail to see its live terminal."

Selection + persistence

  • Click a pane row in the rail. The row highlights (accent-soft background, accent left-border). The detail pane swaps in: pane name + session/branch chips + a Focus-in-tmux button in the header.
  • The detail pane body still shows the "inline terminal coming in a follow-up PR" stub (PR 3 wires xterm).
  • Click the Focus-in-tmux button. Your real tmux client should jump to that pane.
  • Reload the dashboard. The selected pane should still be selected — both rail highlight and detail header restore.
  • Switch to Kanban, then back to Split: selection persists across the layout swap.

Filter interactions

  • Apply a status filter (e.g. "Waiting"). The rail's row list shrinks to match the visible set.
  • If the previously-selected pane is filtered out, the detail pane falls back to the empty-state hint (no orphan selection rendering).

Themes

  • Switch theme to Light, Contrast, Phosphor. All .sb-* surfaces use existing tokens, so colors should adapt without any white-on-white or hard-edged regression.

Out of scope for this PR (don't test these)

  • Rail collapse to a 44px dot strip (PR 2).
  • Divider drag-to-resize (PR 2).
  • Drag-to-reorder rail rows (PR 2).
  • Repo grouping of the rail (PR 2 — consumes THI-243).
  • "+ New tab" row per worktree (PR 2).
  • Inline xterm in the detail pane (PR 3).
  • Detail sidebar with Linked / Notes / Activity sections (PR 3).

🤖 Generated with Claude Code

tdody and others added 2 commits June 7, 2026 10:21
First of three PRs that land the Split view (4th display type in v0.3).
This one ships the smallest viable diff so the layout choice is
reachable end-to-end and the surface is ready for the substantial
follow-ups.

What ships:
- Layout union: "kanban" | "grid" | "list" → adds "split". Updates
  every enumeration (LayoutSwitcher, suggestLayout, etc.).
- New "split" Icon glyph (rail + detail rectangles), stroke-matched
  to the existing layout icons.
- 4th LayoutSwitcher button (Kanban · Grid · List · Split), aria-
  labeled and tooltip'd consistently with the other three.
- New persistent settings:
  * selectedPaneId: "" — which pane the detail pane shows; restored
    on reload + layout swap.
  * splitRailWidth: 280 — divider drag (PR 2) clamps to 200–460.
- New components/split/SplitView.tsx — CSS grid (`rail | 7px | detail`)
  filling .main. PR-1 rail is a flat Session → Pane tree mirroring
  Kanban's sortPendingFirst order; PR 2 swaps this to the
  Repo → Worktree → Pane tree from THI-243's discovery feed.
- New components/split/SplitView.test.tsx (6 tests) covers empty
  state, row rendering, click-to-select persistence, mount-time
  restore, rail-width plumbing, focus-in-tmux callback.
- New .sb-* CSS block (~180 lines) using only existing tokens. PR 1
  styles what PR 1 actually renders; PR 2 adds resize/collapse/drag
  affordances; PR 3 styles the inline xterm chrome.
- App.tsx branches on `layout === "split"` → renders <SplitView/>.
  Other views unchanged.
- suggestLayout never suggests Split (or out of it) — opt-in,
  same as Grid.

Deferred to follow-ups (PR 2 + PR 3 in the same ticket):
- Rail: repo-grouped tree, collapse-to-44px, divider resize,
  drag-to-reorder, "+ New tab" rows (consuming THI-244).
- Detail: inline xterm with reconnect-don't-recreate, header chips
  panel, sidebar (Linked / Notes / Activity).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…split-foundation

# Conflicts:
#	frontend/src/lib/settings.ts
@tdody
tdody merged commit a68fcc6 into main Jun 7, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant