Skip to content

feat: FileTree, an Explorer over a list of paths - #498

Merged
tannevaled merged 1 commit into
mainfrom
feat/filetree
Oct 22, 2026
Merged

tannevaled merged 1 commit into
mainfrom
feat/filetree

Conversation

@tannevaled

Copy link
Copy Markdown
Contributor

A file explorer widget for the go-slides playground's new file panel (themes, kinds, media), generic enough for any app holding a project in memory.

What it is. FileTree shows a flat list of FileEntry (path, folder, size) as VS Code's Explorer does: folders first, then files, by name, with collapse state kept across updates. It never edits its own list. Every change goes out as a FileRequest (open, create, create folder, rename, delete, move, import), the host applies it to its store, then sets Entries(). Selected() is an Observable in both directions.

Interactions.

  • Keyboard. WAI-ARIA APG treeview pattern (https://www.w3.org/WAI/ARIA/apg/patterns/treeview/): arrows, Home/End, Enter, type-ahead, * expands siblings. Explorer keys on top: F2, Delete / Cmd+Backspace, Shift+F10 / the menu key.
  • Rename and New File/Folder. Typed in place. Validation follows VS Code's validateFileName and uses its messages (src/vs/workbench/contrib/files/browser/fileActions.ts).
  • Delete. Asks for confirmation first, with VS Code's wording.
  • Context menu. New File, New Folder, Rename, Delete, then the host's own items (MenuExtra).
  • Drag to move. Dropping a row on a file moves it into that file's folder. A press on a folder toggles it on release, so dragging a folder does not toggle it.
  • Drop from outside. Files dropped from outside go to the folder under the pointer, which is outlined while dragging. DropDirAt lets the host find that folder when it reads the bytes.

Light/dark.

  • The drop outline is the accent when that keeps ≥ 3:1 against the surface; otherwise it falls back to PopupBorder. This is tested across popupThemes().
  • Blocking messages use a red with ≥ 4.5:1 contrast, or the text colour if no red reaches it.

Performance. One Draw takes about 100 µs with 5000 entries at 600 px, since the TreeView is windowed.

Tests. 100% coverage.

🤖 Generated with Claude Code

VS Code's Explorer as a widget, built on TreeView. The host hands it a flat
list of FileEntry (path, folder, size) through the Entries() Observable; the
tree shows folders first, then files, by name, and keeps which folders are
collapsed across updates. Every change is a FileRequest given to OnRequest
(open, create file or folder, rename, delete, move, import); the tree never
edits its own list, so the host's store stays the one source of truth.
Selected() is the selected path, both ways.

- Keys follow the WAI-ARIA APG treeview pattern (TreeView's arrows,
  Home/End, Enter), plus type-ahead (one character steps through the
  matches, quick characters match as a string) and * to expand the
  siblings; F2 renames, Delete (or Cmd+Backspace) asks to delete,
  Shift+F10 / the menu key opens the context menu.
- Rename and New File/Folder are typed in place, validated with the
  Explorer's rules and wording (empty, leading slash, invalid name, already
  exists, a folder into itself; whitespace is a warning).
- Delete asks first, in a footer with Delete/Cancel ("... and its
  contents?" for a folder).
- Context(x, y) opens New File, New Folder, Rename, Delete and the host's
  MenuExtra items.
- A row dragged onto a folder (or a file: its folder) moves there; a press
  on a folder opens it on release, so a dragged folder does not toggle.
- Files from outside (EventDragStart/Move/Drop) go to the folder under the
  pointer, outlined meanwhile; DropDirAt answers the host that reads the
  bytes. The outline keeps >= 3:1 against the surface in light and dark
  (the accent, else PopupBorder); a blocking message uses a red with
  >= 4.5:1, else the text colour.
- Icon picks an icon pack's glyph per entry; the default is Iconoir's folder
  and page. ShowSizes prints sizes (FileSizeText); long names elide.

Draw costs ~100 us for 5000 entries at 600 px (TreeView is windowed).
100% coverage.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@tannevaled
tannevaled merged commit ec115e9 into main Oct 22, 2026
1 check passed
@tannevaled
tannevaled deleted the feat/filetree branch October 22, 2026 08:23
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