Summary
The in-canvas help overlay (Ctrl+/ / Cmd+/ / leader ?) is unusable:
- Red boxes everywhere — dvui duplicate-widget-id outlines, not the TEAL theme.
- Wheel / trackpad over the overlay scrolls the transcript, not the help list.
- The panel is tiny and square (
HELP_OVERLAY_W=460 × HELP_OVERLAY_H=320). On a normal wide desktop it should take most of the transcript band — wide, not a postage stamp.
- Shortcuts do not line up. There is no table: each row is two free
textLayouts in a horizontal box, so chord glyphs and help copy start at whatever width the previous widget reported. Combined with (1) the rows look scrambled.
Operator report: “this thing looks fucking awful.”
Current baseline (live code)
| Claim |
Path / symbol |
Notes |
| Overlay size |
native/harness/src/ui/metrics.zig 69–77 |
Cap 460×320, min band 300×200, 16 px margin. paint does @min(HELP_OVERLAY_W, band − 2×margin) — never grows with a wide canvas |
| Paint |
native/harness/src/ui/help_overlay.zig paint |
Centered absolute dvui.box over the transcript band (ui.zig ~634–651). Not a floatingWindow / subwindow |
| Rows |
same, loop over keymap.KEY_TABLE |
One box (horizontal) + chord textLayout + help textLayout per distinct action. No id_extra |
| Duplicate ids |
dvui WidgetData.init |
Same @src() every iteration → duplicate widget id … highlighted in red → Debug.errorOutline (1 px red stroke). Console will show the err. Nested red rects around every chord/help pair |
| Scroll steal |
ui.zig transcript scrollArea is built first (rect = leftover band); overlay paints after, same screen region, but is not a subwindow |
Wheel / trackpad user_scroll still hits state.transcript_scroll. Overlay has its own ctx_scroll scrollArea that never sees the event |
| Alignment |
no chord column width |
↑/↓ vs Ctrl/Cmd+Enter vs Leader I, then ? are different widths; help text starts at a different x each row |
| Tests |
help_overlay.test.zig |
Pins rowChord strings only. Does not paint, so CI cannot catch (1)–(4) |
| Docs |
docs/harness-limits.md Keyboard |
“Toggle the in-canvas help overlay (TEAL panel over the transcript band)” — no size, no table, no scroll rule |
Goals
| # |
Goal |
Success signal |
| 1 |
No red outlines |
Every loop widget has .id_extra = i (or equivalent unique id). Console has zero duplicate widget id for the overlay. errorOutline never fires on help rows |
| 2 |
Pointer + wheel stay in the overlay while it is open |
Trackpad / mouse wheel over the panel scrolls the help list (ctx_scroll). Transcript user_scroll does not change. Click-outside / Esc still close (Esc already wins over busy cancel) |
| 3 |
Wide panel, most of the transcript band |
On a desktop-width canvas the overlay is wide (use the band, minus a small margin) and tall — not a 460×320 square. ~390 px still usable (no horizontal overflow; table can stack/scroll) |
| 4 |
Table layout |
Two columns: chord (fixed/min width, mono / mixed-text for ↑``↓) and help (remaining width). Every chord starts on the same x; every help string starts on the same x. Grey (WARM-muted) still marks context-off rows |
| 5 |
Rows stay in KEY_TABLE order, one row per distinct action (today’s de-dupe) |
No scrambling from id collision; no second sort unless a later plan asks |
| 6 |
TEAL only (surface / accent / muted). EMBER never — hold vs error. Red is only dvui’s debug stroke, which this plan removes |
Palette-only |
Non-goals / out of scope
Design sketch
- Treat the overlay as a modal in-canvas subwindow (dvui
floatingWindow / equivalent) so event matching hits it before the transcript scrollArea. Wheel stays in ctx_scroll.
- Size: fill the transcript band minus the existing 16 px (or similar) margin — width-first. Drop the 460×320 cap, or replace it with a high fraction of
w/h (named metrics, not magic).
- Rows: one horizontal row per action, chord column + help column (table). Unique
.id_extra on every looping widget (box, both textLayouts, any future cells).
- Keep current open/close (Ctrl+/ · leader
? · Esc) and grey context-off rows.
Testing
| # |
Case |
Layer |
Expected |
| 1 |
Open overlay; console |
harness |
No duplicate widget id for help_overlay widgets |
| 2 |
Layout-rect / testing-backend: overlay open, wheel over panel |
harness |
ctx_scroll.offset moves; transcript_scroll does not |
| 3 |
Wide canvas (e.g. 1280) |
metrics / paint |
Panel width ≫ 460; uses most of the band |
| 4 |
Table columns |
layout |
All chord left edges equal; all help left edges equal |
| 5 |
~390 px |
layout |
Panel on-canvas; no horizontal overflow; list still scrolls |
| 6 |
Esc / Ctrl+/ close |
existing keymap |
Unchanged |
| 7 |
Operator |
browser |
Overlay is a wide table, wheel stays inside, no red boxes |
Gates: zig build test-rich (extend help_overlay beyond rowChord string pins — at least a paint/id_extra / column-x lock) + zig build harness -Doptimize=Debug. Wheel-over-overlay is also operator-gated.
Cloud ops
N/A — no Production mutate. In-canvas chrome only.
Living docs
| Surface |
Change |
docs/harness-limits.md Keyboard & focus |
Help overlay: wide table over the transcript band; wheel stays in the panel; Esc / Ctrl+/ unchanged |
AGENTS.md |
Only if metrics/caps change |
README / SECURITY / .env.example |
N/A |
Refs plan #741 (keymap + overlay) · #761 (leader chord copy) · dvui “duplicate widget id … pass .id_extra=<loop index>”
Summary
The in-canvas help overlay (Ctrl+/ / Cmd+/ / leader
?) is unusable:HELP_OVERLAY_W=460 ×HELP_OVERLAY_H=320). On a normal wide desktop it should take most of the transcript band — wide, not a postage stamp.textLayouts in a horizontal box, so chord glyphs and help copy start at whatever width the previous widget reported. Combined with (1) the rows look scrambled.Operator report: “this thing looks fucking awful.”
Current baseline (live code)
native/harness/src/ui/metrics.zig69–77paintdoes@min(HELP_OVERLAY_W, band − 2×margin)— never grows with a wide canvasnative/harness/src/ui/help_overlay.zigpaintdvui.boxover the transcript band (ui.zig~634–651). Not afloatingWindow/ subwindowkeymap.KEY_TABLEbox(horizontal) + chordtextLayout+ helptextLayoutper distinct action. Noid_extraWidgetData.init@src()every iteration →duplicate widget id … highlighted in red→Debug.errorOutline(1 px red stroke). Console will show the err. Nested red rects around every chord/help pairui.zigtranscriptscrollAreais built first (rect = leftover band); overlay paints after, same screen region, but is not a subwindowuser_scrollstill hitsstate.transcript_scroll. Overlay has its ownctx_scrollscrollAreathat never sees the event↑/↓vsCtrl/Cmd+EntervsLeader I, then ?are different widths; help text starts at a different x each rowhelp_overlay.test.zigrowChordstrings only. Does not paint, so CI cannot catch (1)–(4)docs/harness-limits.mdKeyboardGoals
.id_extra = i(or equivalent unique id). Console has zeroduplicate widget idfor the overlay.errorOutlinenever fires on help rowsctx_scroll). Transcriptuser_scrolldoes not change. Click-outside / Esc still close (Esc already wins over busy cancel)↑``↓) and help (remaining width). Every chord starts on the same x; every help string starts on the same x. Grey (WARM-muted) still marks context-off rowsNon-goals / out of scope
KEYMAP_MAX/LEADER_WINDOW_MSDesign sketch
floatingWindow/ equivalent) so event matching hits it before the transcriptscrollArea. Wheel stays inctx_scroll.w/h(named metrics, not magic)..id_extraon every looping widget (box, both textLayouts, any future cells).?· Esc) and grey context-off rows.Testing
duplicate widget idfor help_overlay widgetsctx_scroll.offsetmoves;transcript_scrolldoes notGates:
zig build test-rich(extend help_overlay beyondrowChordstring pins — at least a paint/id_extra / column-x lock) +zig build harness -Doptimize=Debug. Wheel-over-overlay is also operator-gated.Cloud ops
N/A — no Production mutate. In-canvas chrome only.
Living docs
docs/harness-limits.mdKeyboard & focusAGENTS.md.env.exampleRefs plan #741 (keymap + overlay) · #761 (leader chord copy) · dvui “duplicate widget id … pass
.id_extra=<loop index>”