feat: model menu keyboard machine + graph center-anchor on resize
Owner polish pair before the settings milestone: - Model menu: arrows walk the filtered results (clamped, no wrap) while focus stays in the search field; Enter picks the walked row or, with no walk yet, the first result; typing resets the walk; click and Enter share one pickModel path; walked row gets a muted ring + scrollIntoView; cheat-sheet display entries added. - Graph: window resizes re-anchor the camera so the world point under the pre-resize viewport center stays under the new center — the graph stays visually still while scaling (was top-left pinned). viewW/H tracked in syncSize; re-anchor applied through the zoom behavior (persistence and card-dismiss unchanged); kFit refresh as before. Pixel-verified: 7/7 center samples identical across a 300x200 shrink.
This commit is contained in:
@@ -55,6 +55,18 @@ second pillar of input).
|
||||
| Cheat sheet | ? | keyboard-shortcuts.tsx |
|
||||
| Find (graph: node search) | ⌘F | `lh:kbd-find` (graph-view.tsx; chat transcript search rides the same event when that feature lands) |
|
||||
|
||||
## Model menu keyboard machine (owner polish, 2026-09-17)
|
||||
|
||||
While the model menu is open, focus stays in the search field and the
|
||||
menu owns ↑/↓/Enter inside the input's own handler:
|
||||
|
||||
- **↑/↓** walk the filtered results — clamped, no wrap. First ↓ starts at
|
||||
the first row; first ↑ at the last. The walked row gets a muted ring and
|
||||
scrollIntoView.
|
||||
- **Enter** picks the walked row, or the **first result** when nothing is
|
||||
walked yet (owner decision). Typing a new query resets the walk.
|
||||
- Clicking and Enter share one `pickModel` path; Esc still closes the menu.
|
||||
|
||||
## Question dock row machine (Wave B, owner rounds 2026-09-17)
|
||||
|
||||
While a question is expanded, the dock owns ↑/↓/Space/Enter/Tab:
|
||||
|
||||
@@ -225,3 +225,17 @@ LinLog-only FA2 (one afternoon), then the two-level pipeline
|
||||
(geometry already unit-tested in `components/cluster-geometry.ts`).
|
||||
- Label-gate hysteresis: small dead-band in log-zoom to avoid threshold flicker.
|
||||
- Whether layout runs server-side at extraction (persisted as data) or in-browser.
|
||||
|
||||
## Center-anchor on window resize (2026-09-17)
|
||||
|
||||
The camera translate is measured from the canvas's TOP-LEFT corner, so a
|
||||
window resize used to keep the top-left pinned and the graph appeared to
|
||||
slide by half the size delta (owner report). The resize observer now
|
||||
captures the world point under the PRE-resize viewport center (from the
|
||||
last-synced `viewW/H` — the ResizeObserver already sees the new size in
|
||||
clientWidth/Height), then re-anchors the translate so that same world
|
||||
point lands under the NEW center (applied through the zoom behavior, so
|
||||
d3 state, camera persistence, and card-dismiss all behave like any
|
||||
camera move). Zoom (k) is untouched; `refreshFitZoom` metadata is
|
||||
viewport-bound and recomputed as before. Verified by canvas pixel
|
||||
sampling: 7/7 center-area samples identical across a 300×200 shrink.
|
||||
|
||||
Reference in New Issue
Block a user