feat(shortcuts): tell the key story once, and give the arrows back
Build & publish Arch package / arch-package (push) Successful in 2m1s
CI / check (push) Successful in 2m24s
Search index maintenance / maintain-index (push) Successful in 6s
CI / e2e (push) Canceled after 8s

Decision 1 keeps the unmodified single-key bindings, and Settings was
the only place they were written down — three of the four categories of
them, because config-page listed the categories by hand, so the autotag
keys were written down nowhere at all. `?` now opens an overlay from
anywhere the app owns the keyboard, and both surfaces read one table
(services/shortcut-meta.ts, moved out of config-page's private static).

The other half is the same explanation from the other side. Phase 1
gave the arrow keys to the grid, correctly — but all six of them, and
no list in this app moves horizontally: track-list's own handler and
utils/roving-rows both take Up/Down/Home/End and ignore Left/Right. So
seeking stopped working from a focused row and nothing gained the keys.
Reproduced in the running app: two ArrowRights on a focused track row,
zero Player.Seek calls, against one per press from the body.

A shifted character no longer reports Shift, so the binding is `?` and
not `Shift+?` — the character already carries the shift, and a layout
where it does not is a layout where "Shift+?" is wrong anyway.
This commit is contained in:
2026-08-12 12:33:50 -04:00
parent 4615afe7f7
commit 1aa1598ecb
11 changed files with 730 additions and 164 deletions
+4
View File
@@ -28,6 +28,10 @@ import '@components/first-run-wizard/first-run-wizard.ts';
import '@components/notifications/notification-host.ts';
import '@components/notifications/inline-notice.ts';
import '@components/confirm-dialog/confirm-dialog.ts';
// The `?` overlay: help, so it is eager for the same reason the failure
// surface is — the moment it is asked for is the moment the user does
// not know what is going on. It costs a dialog and a table.
import '@components/shortcuts-overlay/shortcuts-overlay.ts';
import '@components/jobs/job-indicator.ts';
import '@awesome.me/webawesome/dist/styles/themes/default.css';
import '@awesome.me/webawesome/dist/components/icon/icon.js';