The two wide sidebar switchers disagree on button semantics, and #487 phase 3 will
need them to agree.
The UPPER pane's role tabs (src/ui/sidebar-upper.ts:113-119) render each tab with
type="button" and aria-pressed:
h('button', {
class: 'side-tab' + (active === role ? ' active' : ''),
type: 'button',
'aria-pressed': active === role ? 'true' : 'false',
...
The LOWER pane's Library/History tabs (src/ui/saved-history.ts, renderSavedHistory's
tab()) render neither — the active state is conveyed by the active class alone, so a
screen reader hears two plain buttons with no indication of which section is showing.
Both switchers reuse the same .side-tabs/.side-tab/.side-count vocabulary and, since
#487 phase 2, the same NAV_SECTION_META labels — the ARIA is the one thing still
inconsistent between them.
Why deferred: pre-existing (the lower tabs never had it), and #487 phase 2's gate is
explicitly "existing navigation behaviour is unchanged", so changing announced state there
was out of scope. Surfaced by both review passes on PR for #487 phase 2.
Why it matters soon: #487 phase 3 adds a third presentation of these same four
sections — the rail's icon-only launchers, which the issue specifies must carry
aria-expanded + aria-controls. Phase 3 is the natural moment to converge all three on
one announced-state contract rather than adding a third variant. The registry already
carries an accessibleLabel per section for exactly that.
Suggested fix: give the lower tabs type="button" + aria-pressed, matching the
upper pane, and cover it in tests/unit/saved-history.test.ts.
The two wide sidebar switchers disagree on button semantics, and #487 phase 3 will
need them to agree.
The UPPER pane's role tabs (
src/ui/sidebar-upper.ts:113-119) render each tab withtype="button"andaria-pressed:The LOWER pane's Library/History tabs (
src/ui/saved-history.ts,renderSavedHistory'stab()) render neither — the active state is conveyed by theactiveclass alone, so ascreen reader hears two plain buttons with no indication of which section is showing.
Both switchers reuse the same
.side-tabs/.side-tab/.side-countvocabulary and, since#487 phase 2, the same
NAV_SECTION_METAlabels — the ARIA is the one thing stillinconsistent between them.
Why deferred: pre-existing (the lower tabs never had it), and #487 phase 2's gate is
explicitly "existing navigation behaviour is unchanged", so changing announced state there
was out of scope. Surfaced by both review passes on PR for #487 phase 2.
Why it matters soon: #487 phase 3 adds a third presentation of these same four
sections — the rail's icon-only launchers, which the issue specifies must carry
aria-expanded+aria-controls. Phase 3 is the natural moment to converge all three onone announced-state contract rather than adding a third variant. The registry already
carries an
accessibleLabelper section for exactly that.Suggested fix: give the lower tabs
type="button"+aria-pressed, matching theupper pane, and cover it in
tests/unit/saved-history.test.ts.