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

Merged opened this

Check · Review · Land · Live done — Landed and live in production.

Merged

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

opened this

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-dialog through the shared openModal helper. 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, and STATIC_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-written e.key === … branches, not from STATIC_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, select and contenteditable, 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

Closes #10922

commented

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-dialog through the shared openModal helper. 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, and STATIC_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-written e.key === … branches, not from STATIC_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, select and contenteditable, 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

Approved

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.

commented

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).

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs