v2.7.0 - Himinbjörg — one focus + scroll primitive for the TUI
What's Changed
Himinbjörg — one focus + scroll primitive for the TUI
Scrolling was implemented three times in the TUI and behaved differently in each
place; the full-screen top view (t) didn't scroll like the rest, selection lists
let the cursor drift off-screen, and the mouse wheel did nothing in the top view.
This introduces one shared primitive and moves the top view onto it.
Story: docs/stories/himinbjorg-focus-scroll-20260702235455-0021/Story.md
Design: docs/specs/himinbjorg-focus-scroll/design.md · ADR: docs/architecture/0023-tui-focus-scroll-pane-primitive.md
What's in it
- New
app/internal/tui/panepackage — the primitive:Pane: scroll, selection that follows the cursor,/filter, sort cycle,
▲/▼ more · y/totalaffordances, focus ring by border weight (survivesNO_COLOR).Group: grid layout (side-by-side panels), reading-orderTab, two-level
page+pane scroll, pointer-targeted mouse, and a whole-page-first focus stop.- Capability interfaces (
Filterable/Sortable) are opt-in — static panels get neither.
- Top view (
t) runs on the primitive. The whole view is the first focus (↑/↓ +
wheel scroll the entire screen at any resolution);Tabsteps the ring through each
panel and wraps back; wheel/click target the panel under the pointer (was dead here);
the wide 2-column grid is kept.topview's ownscrollWindowcopy is deleted. - Selection stays in view in the command / log-source / sort pickers (
keepSelVisible). - Search / filter, one idiom (
/), extended to every list: command picker (by
name), command result (by output line), and the process view (by command) — on top
of the existing log search. Each clears withescand keeps the cursor in view. - Docs: new
docs/guides/18-using-the-dashboard.md(drive the TUI after setup +
a full keybindings table), corrected12-top-view.md, updated in-app help (?).
Verification
- 303 unit tests green across 29 packages (
go test ./...);go vetclean. - New tests cover the pane math (clamp, keep-visible, page-auto-scroll), grid focus +
mouse hit-testing, whole-page focus, and every new filter. - Top view verified with a headless render (grid alignment, focus ring, whole-page +
page scroll). - Gates: Karpathy 87 (PASS_WITH_APPROVAL), a11y PASS (0 critical/serious,
NO_COLOR-safe).
Deferred (tracked as a follow-up)
Migrating the remaining dashboard modal bodies onto pane.Group so the dashboard's
own scrollWindow copy can be deleted and the Filterable/Sortable API gets a
direct consumer. It's internal dedup with no user-facing change (log/cmd/process
filters already work via the dashboard's own idiom), so it's kept out of this PR to
avoid a large rewrite of a stable view. See the follow-up issue.
Full Changelog: v2.6.3...v2.7.0