Skip to content

tui: the panes are a folding tree, driven by one click - #39

Merged
ralyodio merged 3 commits into
mainfrom
feat/tui-folding-tree
Sep 12, 2026
Merged

tui: the panes are a folding tree, driven by one click#39
ralyodio merged 3 commits into
mainfrom
feat/tui-folding-tree

Conversation

@ralyodio

Copy link
Copy Markdown
Contributor

Follow-up to #38 after trying it: a listing that is replaced on a double-click is not what a mouse user expects from a pane of files. They expect a folding tree, one click, and a row that lights up under the pointer.

Each pane is now that tree, on hqtui 0.5.1 (profullstack/hqtui#87, released for this):

  • One click on a directory unfolds it in place: its listing is fetched (locally, or over the same SFTP session for a server) and drawn indented beneath it, nested as deep as you like. The marker carries the state: folded, unfolded, while the listing is on its way. The next click folds it; the listing is kept so unfolding again is instant. An unreadable directory says so on the status line and stays folded.
  • One click on a file selects it. One click on .. goes up. Double-click is gone.
  • The row under the pointer is lit, a shade lighter than the background, and goes out when the pointer leaves the rows.
  • The keyboard walks the same tree: unfolds, or steps onto the first child of an unfolded directory; folds, else climbs to the parent row, else leaves the root; toggles.

The pane's state grew a children map, an unfolded set, a listing set and a hover index; visibleRows flattens the tree in draw order, which is what the cursor indexes and what a click lands on.

The interaction tests unfold a real directory made under tmpdir, click into its nested directory, fold the parent, walk it with the arrow keys, and prove the hover lights and goes out.

Verified: pnpm build, pnpm -r typecheck, pnpm test against the published @profullstack/hqtui@0.5.1.

🤖 Generated with Claude Code

https://claude.ai/code/session_01DWtLsmAescX4Nb8QiBJd37

ralyodio and others added 3 commits September 12, 2026 20:55
The first pass at the mouse copied a file manager from 1990: a click moved
the cursor and a double-click walked into a directory, replacing the listing
with a new one. That is not what a mouse user expects from a pane of files
today. They expect the directory to open in place, under its own name, on
one click, and to close the same way, with the rest of the listing still on
screen around it. And they expect the row under the pointer to say so.

Each pane is now that tree:

- One click on a directory unfolds it: its listing is fetched (locally, or
  over the same SFTP session for a server) and drawn indented beneath it,
  nested as deep as you like. The marker on the row carries the state: ▸
  folded, ▾ unfolded, … while the listing is on its way. The next click
  folds it again, and the listing is kept so unfolding is instant. A
  directory that cannot be read says so on the status line and stays folded.
- One click on a file selects it. One click on `..` goes up.
- The row under the pointer is lit, a shade lighter than the background, and
  goes out when the pointer leaves the rows. The frame's own tree hears the
  pointer only while it is inside, so the app's mouse listener notices the
  move that no row claimed.
- The keyboard walks the same tree: → unfolds a folded directory and steps
  onto the first child of an unfolded one, ← folds the directory under the
  cursor, else climbs to its parent row, else leaves the root. ⏎ toggles.
  Double-click is gone; nothing needs it.

The pane's state grew a `children` map (listing by relative path), an
`unfolded` set, a `listing` set and a `hover` index; `visibleRows` flattens
the tree in draw order, which is what the cursor indexes and what a click
lands on. The view draws it with hqtui 0.5.1's tree, whose new `onRow`
callback and `hovered` option are what made this possible.

The interaction tests now unfold a real directory made on disk under
`tmpdir`, click into its nested directory, fold the parent, walk it with the
arrow keys, and prove the hover lights and goes out.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DWtLsmAescX4Nb8QiBJd37
pnpm's minimumReleaseAge policy holds new packages for a day, and the local
install had already written the exclusion for our own hqtui into the
workspace file; this commits it so the frozen install in CI agrees.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DWtLsmAescX4Nb8QiBJd37
@socket-security

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Updated@​profullstack/​hqtui@​0.5.0 ⏵ 0.5.184100100 +196100

View full report

@ralyodio
ralyodio merged commit af6002a into main Sep 12, 2026
4 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