Skip to content

refactor: show a flat file list in the Changes tab - #585

Open
EyalShechtman wants to merge 2 commits into
dcouple:mainfrom
EyalShechtman:diffs-ui-view
Open

EyalShechtman wants to merge 2 commits into
dcouple:mainfrom
EyalShechtman:diffs-ui-view

Conversation

@EyalShechtman

Copy link
Copy Markdown

Summary

The Changes tab stacked a commit-history list above a nested folder tree. In a narrow inspector the split flipped to a column capped at 45% height, so the commit list ate roughly half the panel before a single file was visible.

This replaces the tree with a flat, single-scope file list — a dimmed directory prefix that absorbs truncation beside a basename that always renders in full — and drops the commit list entirely. The whole-branch diff remains the default scope, Commit/Restore move to the panel header, and the inspector now opens on Changes.

Before / after

Before After
Commit list (~45% of the panel) above a nested folder tree One flat file list for the current scope
Basenames truncated away at narrow widths Directory prefix truncates; basename always whole
Inspector opened on Details Inspector opens on Changes

Screenshots

Inspector at 420px — the primary target width:

Changes tab at 420px

300px and 580px — the directory prefix absorbs truncation at every width. At 300px the per-row stats hide via the pre-existing @container (max-width: 320px) rule inherited from the old tree:

300px 580px
300px 580px

State variants — Commit/Restore appear only when uncommitted work exists; the "All changes" escape button and Revert appear only under a commit scope:

No uncommitted changes Commit scope (via Details history graph)
committed only commit scope

Full window at 420px:

full window

What changed

Added

  • frontend/src/components/panels/diff/changesListModel.tsbuildChangesRows splits each path into a dir prefix and name; navigateList and typeAhead replace the tree's keyboard model.
  • frontend/src/components/panels/diff/ChangesList.tsx — flat virtualized list. Ports the tree's virtualization, ResizeObserver measurement, useScrollSurface registration, perf marks, and click/double-click semantics unchanged.
  • frontend/src/components/panels/diff/changesList.test.ts — unit coverage for the model.

Removed

  • frontend/src/components/ExecutionList.tsx — the commit list.
  • ChangesTree.tsx, changesTreeModel.ts, changesTree.test.ts — superseded by the flat list.
  • .pane-review-* CSS and the @container (max-width: 600px) stacking block that caused the cramped layout.
  • The sidebar-resize state, expansion state, and range-selection plumbing in CombinedDiffView.tsx (−197 lines).

Changed

  • CombinedDiffView.tsx — single-column body; header carries the scope label, stats, Commit/Restore, Revert, and Refresh.
  • ProjectView.tsx / SessionView.tsx — default inspector tab is now changes. DetailPanel's existing showDetails = inspectorTab === 'details' || !hostedPanel fallback means this degrades safely when no changes panel exists.

Deliberate decisions

  • Commit ranges lose their UI, keep their types. Shift-click range selection went with the commit list, but commit-range and working-tree-range stay in shared/types/gitDiff so already-open and persisted editor diff tabs still resolve. No data migration.
  • diff:view-commit still works. The Details tab's history graph can still hand a commit to this panel, which is why the header keeps an "All changes" button — without it, that handoff would be a one-way trip.
  • Revert stayed. ExecutionList was the only other caller of the git:revert IPC; dropping it would have made revert unreachable from the entire app. It now renders gated on scope.kind === 'commit'.
  • A11y role changed from tree to listbox. A flat list of files is a listbox; keeping tree would have had screen readers announcing nesting levels that no longer exist. This is why the spec files have a large diff.
  • Perf mark names kept as pane-diff-tree-* despite no longer being a tree — they're a measurement contract with the perf harness. Commented as such.

Verification

  • pnpm typecheck — clean across frontend, main, runpane, shared
  • pnpm lint — 0 errors (5 pre-existing warnings in main/src/services/skillCacheManager.ts, unrelated); Knip clean
  • pnpm --filter frontend test — 324 tests / 33 files
  • pnpm test on the affected specs — 45 tests, including axe checks on .combined-diff-view
  • pnpm run build:frontend and pnpm run build:main

Specs renamed changes-tree*changes-list* and reworked for the new roles. theme-screenshots.spec.ts also queried the old treeitem role and needed the same swap.

Notes for review

  • The load-bearing detail is the flex pair in .pane-changes-list-dir (flex: 0 1 auto, min-width: 0) and .pane-changes-list-name (flex: 0 0 auto). Inverting them would truncate filenames and preserve useless directory prefixes.
  • At 300px the header truncates to "All …" while Commit/Restore compete for the same row. That reads worse than before now that the header carries actions — a reasonable follow-up, not addressed here.
  • The screenshots are committed under screenshots/changes-redesign/ so they render above. Happy to drop that commit if you'd rather not carry them in the repo.

https://claude.ai/code/session_01RX4RqNL69dAxVoaETQE57D

The Changes tab stacked a commit-history list above a nested folder tree.
In a narrow inspector the split flipped to a column capped at 45% height,
so the commit list ate half the panel before a single file was visible.

Replace the tree with a flat, single-scope file list: a dimmed directory
prefix that absorbs truncation beside a basename that always renders in
full, with the stats and status letter right-aligned. Drop the commit
list entirely -- there is no user story for browsing other commits here,
and the whole-branch diff remains the default scope. Commit and Restore
move to the panel header, and the inspector now opens on Changes.

The Details tab's history graph still hands a commit off via
diff:view-commit, so the header keeps an "All changes" button to get
back, and Revert stays reachable under a commit scope -- ExecutionList
was the only other caller of the git:revert IPC.

Shift-click commit ranges lose their UI, but the commit-range and
working-tree-range scope kinds stay in shared types so already-open and
persisted editor diff tabs still resolve.

Plan: tmp/done-plans/changes-tab-flat-list.md

Claude-Session: https://claude.ai/code/session_01RX4RqNL69dAxVoaETQE57D
Captured from a Playwright fixture at three inspector widths plus the
committed-only and commit-scope states. Each shot asserts the UI state
before capturing.

Claude-Session: https://claude.ai/code/session_01RX4RqNL69dAxVoaETQE57D
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