Skip to content

Commit 6ac9aea

Browse files
committed
fix: name the pane pin button and expose whether it is pinned
The button that pins the discussion list carries only an icon, and unlike the back and drawer buttons either side of it, nothing that names it. A screen reader reaches it and can say no more than "button". Core already notices: Button warns in the console when it finds no content and no accessible label, and this button has been tripping that warning rather than being read as an omission. It is also a toggle, and its state was carried entirely by the icon rotating forty-five degrees when unpinned. Nothing about being pinned was exposed to assistive technology at all. The label names the control rather than the action, so it holds still while the state changes underneath it; `aria-pressed` reports whether it is currently on. Naming it for the action instead would mean a screen reader reading a button whose name changes under it, with the state never stated. `aria-pressed` is given as a string rather than a boolean on purpose. Mithril renders a boolean as an HTML boolean attribute, so `false` omits the attribute entirely and `true` renders it empty. Neither is valid ARIA, and an absent `aria-pressed` reads as a plain button rather than as a toggle that happens to be off. Core has no other use of the attribute, so there was no local precedent to follow here.
1 parent e792ca2 commit 6ac9aea

2 files changed

Lines changed: 12 additions & 0 deletions

File tree

framework/core/js/src/common/components/Navigation.tsx

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,17 @@ export default class Navigation extends Component {
7070
className={classList('Button Button--icon Navigation-pin', { active: pane.pinned })}
7171
onclick={pane.togglePinned.bind(pane)}
7272
icon="fas fa-thumbtack"
73+
// The label names the control and stays put; `aria-pressed` carries
74+
// whether it is currently on. Swapping the label for the action instead
75+
// ("Pin"/"Unpin") would leave a screen reader reading a button whose
76+
// name changes under it, with the state only ever implied.
77+
//
78+
// Stringified deliberately: Mithril treats a boolean as an HTML boolean
79+
// attribute, so `false` omits it altogether and `true` renders it empty.
80+
// ARIA needs the words, and an absent `aria-pressed` makes this read as
81+
// a plain button rather than a toggle that happens to be off.
82+
aria-label={app.translator.trans('core.lib.nav.pin_pane_button')}
83+
aria-pressed={pane.pinned ? 'true' : 'false'}
7384
/>
7485
);
7586
}

framework/core/locale/core.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -953,6 +953,7 @@ core:
953953
# These translations are used in the navigation header.
954954
nav:
955955
drawer_button: Open Navigation Drawer
956+
pin_pane_button: Pin Discussion List
956957

957958
# These translations are used in forum & admin notices.
958959
notices:

0 commit comments

Comments
 (0)