fix(a11y): make Settings and the Downloads tabs keyboard-reachable

a11y.1 is the audit's last Critical and reproduced exactly: seven
config-section headers, seven bare `<div @click>`s with no tabindex,
no role and no aria-expanded, and every section collapsed by default —
so every setting in the app was behind a control that could not be
tabbed to. a11y.2 is the same bug in Downloads' two `<div class=tab>`s.

Both now follow patterns the app already had: a real
`<button aria-expanded aria-controls>` (explore-artist-details has five),
and a role=tablist/tab/tabpanel with a roving tab stop and
Left/Right/Home/End. The section body renders unconditionally and is
toggled with `hidden`, because aria-controls has to name an element
that exists and the slot's light-DOM children exist either way.

H-22's reorder ships with them: Libraries is first and the only
expanded section, Search Index — configured once, if ever — is second
to last. The Playback/Audio section H-22 also asks for is deliberately
not here: there is no output-device, gapless, crossfade or replay-gain
setting in backend/config to expose, and a section of controls that do
nothing is worse than admitting it does not exist.

Settings also stops advertising `tracklist.delete`, which was bound to
Delete and configurable in the UI while nothing listened for the event
it dispatched.
This commit is contained in:
2026-08-12 12:12:33 -04:00
parent a150b24e71
commit 24887d6840
6 changed files with 240 additions and 42 deletions
+9 -3
View File
@@ -32,9 +32,15 @@ func DefaultBindings() map[string]string {
// App actions (Global scope, Ctrl modifier)
"app.selectAll": "Ctrl+A",
// Panel-specific (track list)
"tracklist.play": "Enter",
"tracklist.delete": "Delete",
// Panel-specific (track list). There is no `tracklist.delete`:
// it was bound to Delete and advertised in Settings as
// configurable while nothing listened for it, because "remove
// from library" does not exist and it is not clear what it would
// remove — the row (which the next scan puts back unless the path
// is also excluded) or the file (a delete-your-music button one
// keystroke from a focused row). Advertise it again when it does
// something.
"tracklist.play": "Enter",
// Panel-specific (autotag review). These are the keys the
// autotag page used to bind on its own document listener, which