Skip to content

Code mode: file tree with responsive collapse#570

Merged
blove merged 14 commits into
mainfrom
claude/code-mode-file-tree
Jun 4, 2026
Merged

Code mode: file tree with responsive collapse#570
blove merged 14 commits into
mainfrom
claude/code-mode-file-tree

Conversation

@blove
Copy link
Copy Markdown
Contributor

@blove blove commented Jun 4, 2026

Summary

  • Adds a VS Code / Zed-style file tree on the left of the Code-mode tab strip at lg: widths (≥1024px); below lg: the tree auto-hides and Code mode falls back to today's tabs-only layout.
  • All files from the content bundle are pre-opened as tabs; clicking a tree row activates the matching tab if open, or opens a new tab if not.
  • Each tab gains a close (×) button (hover or active) with keyboard support (Enter/Space); closing the active tab activates its left neighbor; closing the last tab shows an empty state.
  • Tree has a persistent collapse toggle (chevrons in aside header + right column), state persisted in localStorage under cockpit:codeTree:collapsed; hydration-flash is suppressed via a mounted gate so returning users don't see an animated collapse on reload.
  • buildTree(paths) is a pure utility with VS Code-style "Compact Folders" — single-child folder chains merge into one row (e.g. angular/src/app).
  • Folds in a tighter prose layer: .cockpit-prose--wide and .cockpit-prose--code width modifiers, Code-mode cockpit-prose--code 56rem wrapper, API mode py-6 for outer-pane consistency with Docs.

Spec & plan

  • Spec: `docs/superpowers/specs/2026-06-03-code-mode-file-tree-design.md`
  • Plan: `docs/superpowers/plans/2026-06-03-code-mode-file-tree.md`

Test plan

  • At ≥1024px: tree visible left of tabs; click any tree row activates the matching tab; tree row + active tab stay in sync.
  • Hover any tab → × appears; click × → tab closes, left neighbor activates; close all tabs → "Select a file from the tree to begin" empty state; click a tree row → reopens.
  • Keyboard-only: Tab to the close button on the active tab, press Enter → tab closes.
  • Click the ‹ chevron in the tree header → tree slides closed with a 200ms transition; expand chevron (›) appears in the right column; click → tree slides open. Reload → collapsed state persisted.
  • At <1024px: tree hidden; tabs span full width; close × still works.
  • Toggle the cockpit theme (sidebar toggle) → tree colors flip correctly; embedded RunMode iframe theme handshake unchanged.

🤖 Generated with Claude Code

blove and others added 14 commits June 3, 2026 19:30
Adds a file tree on the left of the Code-mode tab strip at lg+, with all
files pre-opened as tabs, tree-click activates existing tab or opens new,
close X on tabs, no cross-capability persistence, collapse persisted via
localStorage. No new deps; pure presentational FileTree + state moved
into CodeMode.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
8 tasks: land prerequisite prose/padding work, buildTree utility (TDD),
CodeMode state migration to openPaths+activePath, FileTree component (TDD),
lg: responsive split + tree-click integration, tab close (×) + last-tab
empty state, collapse toggle with localStorage, full verification.

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

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Pure function that converts flat file paths into a compact tree with
VS-Code-style single-child folder merging and namespace-prefix peeling.
All 6 unit tests green.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ashes

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Wrap file label in <span data-file-label> for text-overflow to work on
flex children; move chip inside the button so clicking it fires onSelect;
remove role="tree" from the outer <ul> (no treeitem/group/arrow-key
support). Update both spec assertions to query [data-file-label].

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Places the FileTree to the left of the tab strip at lg:+ widths, hidden below. Wires onSelect to openPaths/activePath handlers so tree-clicks activate existing tabs or open and activate new ones.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds × close affordance on each Code-mode tab (visible on hover / active tab).
Closing a tab removes it from openPaths, activates the left neighbor (or new
leftmost if first was closed), and shows a "Select a file from the tree to
begin." empty state when all tabs are closed. TDD: 2 new passing tests; 6
pre-existing tests updated to strip × from textContent comparisons.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Render <Tabs> only when openPaths.length > 0 and activePath !== null; show
  empty-state as the exclusive alternative (eliminates Radix controlled→uncontrolled
  warning on last-tab-close).
- value={activePath} without ?? undefined inside the guarded branch.
- Add tabIndex={0} and onKeyDown (Enter/Space) to close <span> for a11y.
- Remove unreachable ?? next[0] fallback in handleClose.
- Hoist getTabLabel(path) to a single const per map iteration.
- Add keyboard-close test (9 total in code-mode.spec.tsx).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…for smooth transition

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@vercel
Copy link
Copy Markdown

vercel Bot commented Jun 4, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
threadplane Ready Ready Preview, Comment Jun 4, 2026 3:13am

Request Review

@blove blove enabled auto-merge (squash) June 4, 2026 03:09
@blove blove merged commit 006d420 into main Jun 4, 2026
42 of 43 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