feat(desktop): the file tree draws coloured icons, shares a lone folder's row, and gains a search field and a Files Luke showed filter
Merged
DA
7d ago+510+510+012345678901234567890123456789-56-56-01234567890123456789
Part 1 of 3 of Dean's file viewer polish. Part 2 (whole-repository search) and part 3 (one top bar: back/forward, breadcrumbs, GitHub, ⋯ menu, collapse) stack on this one.
Summary
The tree beside a File tab:
- Draws coloured file icons.
icons: "complete". Pierre colours only its Complete set (it marks the treedata-file-tree-colored-icons), and Standard was monochrome. - Shares a lone folder's row.
flattenEmptyDirectories: true, soapps/web/serveris one row, as in an editor's explorer. The tree is listed one folder at a time, and Pierre gives the shared row the expansion of the folder at its end. That folder is not listed yet when its parent opens, so a folder holding nothing but one folder now also opens that folder (folder-browser.ts). Otherwise the shared row would show as closed just after you opened it. - Has a search field at its top, in place of the repository-name header. The repository is already the first breadcrumb.
- It uses the app's search-field style (the Settings well, a step shorter).
- It filters the tree as you type through Pierre's own search (
setSearch, hide-non-matches). It matches on the path, case-insensitively, and opens the folders above each match. - When nothing matches, the tree's place says No files match. Without this, Pierre would show every row.
- Escape clears the field, then lets go of the caret. ⌘F (Ctrl+F) anywhere in the pane takes the caret to the field. Nothing else in the window offers ⌘F while a plan is open.
- In this PR the search covers only the folders listed so far. Part 2 makes it search the whole repository.
- Has a filter beside the search: "Only files Luke showed". It is a toggle icon button (
aria-pressed) that narrows the tree to the files Luke showed of this repository, every folder open. It is disabled with a tooltip while Luke has shown none. A "Changed files" filter does not apply: the viewer reads the default branch as it stands, so nothing is changed. The filter is a second Pierre tree over those paths that stands in the repository tree's place, so turning it off leaves the repository's open folders as they were. Search works inside it too. - A breadcrumb's folder clears the search and the filter, because pressing a breadcrumb asks to see that folder.
Bundle
renderer/file-tree.js grew +9 gz bytes (70,853 → 70,862; budget 70,635 × 1.05 = 74,166). Pierre already shipped every icon sprite. The budget is not moved, and renderer.js is unaffected beyond the pane's few lines.
Screenshots (headless Chrome, fixture data)
Light, colored icons, apps/web sharing a row | ![]() |
| Dark | ![]() |
Search .ts | ![]() |
| Filter: files Luke showed (dark) | ![]() |
| No match | ![]() |
Verification
./scripts/check.shexits 0.- New tests, each failing without the change:
file-tree/index.test.ts(the real bundle on real Pierre in jsdom): icons are coloured and typed; search narrows rows, says when none match, and an empty search restores them; the filter shows only the given files with folders open, opens a file on a press, searches within, and lets go.file-tree/folder-browser.test.ts: a folder holding one folder opens it too, and the shared row lists what it holds.planning/file-view.test.ts: the field hands the tree the query; Escape clears it; ⌘F focuses it; the filter narrows to this repository's shown files; a breadcrumb's folder clears both; the filter is disabled while Luke has shown nothing.
- Session replay: the pane stays
ph-no-capture, and the field is inside it. - CI could not verify this. It is a desktop UI change and
./scripts/verify.shwas not run: this was written on a Linux VM. A Mac break that lands is caught at the release rehearsal on a tag (LUKE-159).
🤖 Generated with Claude Code




