Public: anyone can read this; the crew can change it.
`?` opens a keyboard sheet listing the keys of the page you are on, and j/k/enter/esc work the same on every list #10977
Check · Review · Land · Live done — Landed and live in production.
This pull only adds `test/keyhelp.test.ts`. The keyboard sheet itself was already on main, so I changed nothing in `src/web/client.ts` or `src/web/palette.ts`.
shipped production is serving it deploy b9c19dd
This pull only adds test/keyhelp.test.ts. The keyboard sheet itself was already on main, so I changed nothing in src/web/client.ts or src/web/palette.ts.
Already on main
- Sheet:
?opens#help-dialogthrough the sharedopenModalhelper. That helper closes the dialog on Esc and puts focus back where it was. The dialog sits outside the page flow, so nothing shifts. - Key table: the sheet renders the page's own
[data-shortcut]elements, the page-specific keys, andSTATIC_KEYS(j/k, o/Enter,/, Cmd/Ctrl K,:,?, Esc).test/help-keys.test.ts, which was already there, checks both directions: every key the handler answers has a row, and every row is answered. The handler still matches keys by hand-writtene.key === …branches, not fromSTATIC_KEYS. So the issue's "built from the same table the handlers use" is met by that test, not by one shared table. - Typing in a field: the keydown handler returns early for
input,textarea,selectandcontenteditable, apart from Esc to blur and Cmd/Ctrl+Enter on forms that ask for it. It also returns early for anything inside an open dialog.
What the new test checks
- The field guard returns before any of j, k, o,
?,/,:, c or C is read. - An open dialog owns its keys.
- j/k, enter, esc and
?are rows in the table the sheet renders. - The sheet opens through
openModal, which handles Esc and returns focus. - The sheet is built from DOM nodes, never
innerHTML.
These are source-level checks, in the style of the existing help-keys.test.ts. They run no browser, so Esc returning focus and the light and dark rendering are not exercised. The sheet reuses the existing .table and .dialog classes and design-lint is clean, but I did not view it in a browser.
Not done: I did not merge the handler and STATIC_KEYS into one data structure. It would change a 2,500-line inline script, and the existing two-way test already stops the two from drifting.
Checks run: bun test test/keyhelp.test.ts test/help-keys.test.ts passes (9 tests). bun x tsc --noEmit and bun scripts/design-lint.ts are clean. I did not run scripts/gate.ts or scripts/fast.ts.
Try it: press ? on any page, then Esc.
🤖 Generated with Claude Code
The sheet already exists on main and the preview serves #help-dialog; this pull adds only source-level tests, which is honest and small. Next two things: (1) drive the handler from STATIC_KEYS so the sheet and the handlers are literally one table instead of two tables held together by a test; (2) add a real browser check (or a DOM-level test) for Esc returning focus and for the sheet in light and dark, instead of matching source strings that break on any refactor of client.ts.
Left #10922 open: 2 unticked items remain (the sheet is built from the same table the handlers use, so it cannot list a key that does nothing; a test covers the table and the field guard; looks light and dark).
This pull only adds
test/keyhelp.test.ts. The keyboard sheet itself was already on main, so I changed nothing insrc/web/client.tsorsrc/web/palette.ts.Already on main
?opens#help-dialogthrough the sharedopenModalhelper. That helper closes the dialog on Esc and puts focus back where it was. The dialog sits outside the page flow, so nothing shifts.[data-shortcut]elements, the page-specific keys, andSTATIC_KEYS(j/k, o/Enter,/, Cmd/Ctrl K,:,?, Esc).test/help-keys.test.ts, which was already there, checks both directions: every key the handler answers has a row, and every row is answered. The handler still matches keys by hand-writtene.key === …branches, not fromSTATIC_KEYS. So the issue's "built from the same table the handlers use" is met by that test, not by one shared table.input,textarea,selectandcontenteditable, apart from Esc to blur and Cmd/Ctrl+Enter on forms that ask for it. It also returns early for anything inside an open dialog.What the new test checks
?,/,:, c or C is read.?are rows in the table the sheet renders.openModal, which handles Esc and returns focus.innerHTML.These are source-level checks, in the style of the existing
help-keys.test.ts. They run no browser, so Esc returning focus and the light and dark rendering are not exercised. The sheet reuses the existing.tableand.dialogclasses anddesign-lintis clean, but I did not view it in a browser.Not done: I did not merge the handler and
STATIC_KEYSinto one data structure. It would change a 2,500-line inline script, and the existing two-way test already stops the two from drifting.Checks run:
bun test test/keyhelp.test.ts test/help-keys.test.tspasses (9 tests).bun x tsc --noEmitandbun scripts/design-lint.tsare clean. I did not runscripts/gate.tsorscripts/fast.ts.Try it: press
?on any page, then Esc.🤖 Generated with Claude Code
Closes #10922