Skip to content

0.4.0: collapse that reaches every seam, and the world map in the demo - #83

Merged
ralyodio merged 1 commit into
mainfrom
worktree-collapse-gaps-and-demo-map
Sep 9, 2026
Merged

0.4.0: collapse that reaches every seam, and the world map in the demo#83
ralyodio merged 1 commit into
mainfrom
worktree-collapse-gaps-and-demo-map

Conversation

@ralyodio

@ralyodio ralyodio commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

Two bug reports from running bunx @profullstack/hqtui-demo on a seedbox, and the release that gets the fixes to bunx.

c only collapsed half the panels

Two distinct causes, one on top of the other.

The gaps. Every screen computes panelGap(state) — zero while collapsed — and used it for the seams inside its columns. But the row that splits the screen into left and right was written gap: 1 in six screens, so those seams could never close. themes.ts never imported panelGap at all, and the three sub-panels inside the dashboard's System panel were the same oversight one level down.

The wrapper. Closing the gaps was necessary and not sufficient: the panels then touched but still drew two borders. A seam merges only where two bordered siblings meet, and the only way to put a stack of panels beside one tall panel is to wrap the stack in a column — which is not itself bordered. So the middle seam of every screen was the one seam that could never merge, and a grid never merged at all. The dashboard looked right only because its panels happen to be direct children of the row.

Containers now take a bordered flag declaring that their own edges are panel borders, and a grid of panels merges its tracks. It is declared rather than inferred because the children are built only once the layout has been solved, and the seam has to be known before that.

And backgrounds. box filled its whole rect before drawing its border, erasing the neighbour's border out of the shared column — so the merge found a blank cell and overwrote it, leaving a corner where a junction belonged. Filling under collapsing now stops at the border ring, which the border paints in the same background.

Landed in all seven implementations together: TypeScript, Rust, Go, Python, Zig, C/C++, and the Ruby/PHP/Perl bindings that ride on the C++ demo.

The world map was not in the demo

The map has been in the library since #82, but that PR shipped examples/world.ts and touched nothing under apps/demo/. So bunx @profullstack/hqtui-demo showed no map anywhere.

It is a screen now, on w: hover to read the country under the cursor, click to select, z to zoom to the selection, r to go back to the globe. The country list and the map are two views of one selection rather than two kept in step — the list's pane index is the selection, so the arrows move the highlight on the map for free and a click on the map only has to move the list.

Digits run out at ten screens, so the eleventh takes a letter and the tab labels read their key from SCREEN_KEYS rather than recomputing (i + 1) % 10, which would have printed a second 1 and shadowed the dashboard.

0.4.0

The demo has to move with the library rather than after it: it now calls worldMap, which does not exist in the published 0.3.0, so a demo published against ^0.3.0 would resolve the old library and crash on the world screen.

Uncollapsed rendering is untouched

The regenerated demo-parity.json proves it: of 240 cases, all 120 open frames are byte-identical and 90 of the 120 collapsed ones changed.

Checks

  • TypeScript: 356 tests under both bun test and node --test
  • Go: all suites; Python: 36 tests; Rust: 17 demo-parity; Zig: 17; C++: 9/9 including its own 240-case parity
  • Ruby and Perl bindings: each reports 240 exact reference frames in both border modes (PHP's extension needs phpize, built in CI)
  • Rendering all eleven screens both ways and counting seams that stayed open gives zero on every one
  • bun install --frozen-lockfile clean; node apps/demo/bin/hqtui-demo.mjs --version prints hqtui-demo 0.4.0

🤖 Generated with Claude Code

https://claude.ai/code/session_01VhrgsHr1C5BYxXDpN1mahf

Two things the demo promised and did not do.

`c` toggled collapsed borders and only half the panels moved. Every screen
already computed `panelGap(state)`, which is zero while collapsed, and every
screen used it for the seams inside its columns -- but the row that splits the
screen into left and right was written `gap: 1` in six of them, and the library
only merges a seam where two bordered siblings actually touch. So the vertical
stacks closed up and the one seam running down the middle of the screen never
did, on every tab after the dashboard. themes.ts never imported panelGap at all,
and the three sub-panels inside the dashboard's System panel were the same
oversight one level down.

Rendering all eleven screens both ways and counting seams that stayed open now
gives zero on all of them, where six screens had an open seam before.

The world map has been in the library since #82 but was only ever reachable
from examples/world.ts, so `bunx @profullstack/hqtui-demo` showed no map
anywhere. It is a screen now, on `w`: hover to read the country under the
cursor, click to select, z to zoom to the selection and r to go back.

The country list and the map are two views of one selection rather than two
that have to be kept in step -- the list's pane index *is* the selection, so the
arrow keys move the highlight on the map for free and a click on the map only
has to move the list.

Digits run out at ten screens, so the eleventh takes a letter and the tab
labels read their key from SCREEN_KEYS rather than recomputing `(i + 1) % 10`,
which would have printed a second "1" and shadowed the dashboard.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VhrgsHr1C5BYxXDpN1mahf
@ralyodio
ralyodio merged commit 0ea21be into main Sep 9, 2026
14 checks passed
@ralyodio ralyodio changed the title Close every panel seam on collapse, and put the world map in the demo 0.4.0: collapse that reaches every seam, and the world map in the demo Sep 9, 2026
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