feat(ui): scroll the focused sidebar panel + refine the nav overlay (#21, ADR-0046 DC3 + DC2)

DC3 — navigation-mode scroll: the focused Tables / Relationships panel
scrolls (Up/Down by a line, PageUp/PageDown by its visible-row count).
Per-panel offsets are clamped to content at render time, and the
renderer reports each panel's visible rows for paging — mirroring the
output panel's scroll. render_items_panel / render_relationships_panel
take &mut App, count their rows, and store+clamp the offset before
building the borrowing lines.

DC2 refinement: the expand-on-focus overlay now clears only the sidebar
strip plus a one-column gutter, leaving the base output/input/hint
visible (unchanged) to the right rather than blanking the whole area —
truer to "underneath keeps its layout", with the gutter keeping the
cut-off edge clean (chosen after eyeballing both variants). ADR DC2 and
the overlay snapshot updated to match.

Tests: line/page scroll move only the focused panel and clamp; the
render clamps a past-the-end offset so the last row stays visible.
This commit is contained in:
claude@clouddev1
2026-06-10 21:27:13 +00:00
parent c9da6ff785
commit 22bec61d11
4 changed files with 191 additions and 47 deletions
@@ -320,14 +320,23 @@ input-editing arms and routes keys per DC3/DC4.
### DC2 — Expand-on-focus as an overlay
A focused sidebar panel widens to **~4050 columns**, rendered as an
**overlay**: the renderer draws a `Clear` over the affected right-column
region and paints the wide panel on top. The output/input/hint panels
underneath keep their exact layout — **unused and unchanging** while
browsing — and are restored by the next frame on exit. This is cheap
because the renderer is a pure function of `App` state: focus state
selects the width and the overlay path. (The input underneath is
inactive in navigation mode, so occluding it is harmless.)
A focused sidebar panel widens to a **45-column** overlay
(`NAV_EXPANDED_WIDTH`): the renderer `Clear`s the strip the expanded
panel occupies **plus a one-column gutter** (`NAV_OVERLAY_GUTTER`) and
paints the wide panel on top. The output/input/hint panels underneath
keep their exact layout — **unused and unchanging** while browsing,
**still visible to the right** of the overlay (just partially occluded
on the left) — and are restored fully by the next frame on exit. The
gutter keeps them from butting against the expanded panel's border so
the overlay edge reads cleanly. This is cheap because the renderer is a
pure function of `App` state: focus state selects the width and the
overlay path. (The input underneath is inactive in navigation mode.)
*Implementation note (2026-06-10):* a full-area clear (hiding the base
panels entirely during browse) was tried first and rejected — leaving
the base visible is truer to "underneath keep their layout," and the
one-column gutter resolves the only wrinkle (the panels' left edges
being cut by the overlay reading harshly without separation).
### DC3 — Scroll the focused panel; focus highlight