Everything written this session that has not been through the device: rounds 43 to 48 (each patch adversarially verified, 43's transient-notice expectation fixed), a partial round 49, the pipeline scripts, the Android Auto design and the icon comparison mock. Also the two harness changes that were never A/B'd — adaptive waits, which may only shorten a declared wait and never lengthen it, and a ship that runs the mock walk and the deploy at the same time. The A/B and its 255-step baseline are in handoff/tools; main stays at what the phone has actually walked.
69 lines
3.8 KiB
Plaintext
69 lines
3.8 KiB
Plaintext
## What a screen reader says
|
|
|
|
Every control on the phone is named by what it does, in the app's own
|
|
words, and where the desktop already has a word for something it is the
|
|
word used here too — Seek, View album artwork, Close artwork viewer. An
|
|
icon-only control carries an `aria-label`; one with visible text is named
|
|
by the text it shows.
|
|
|
|
The nav is a tab set: `role="tablist"` on the bar, `role="tab"` and
|
|
`aria-selected` on the five destinations, and the count badge round
|
|
seventeen added is part of the tab's own name — "You, 3 transfers",
|
|
"Community, 2 unread" — rather than a digit read out before the word it
|
|
belongs to. The badge itself is `aria-hidden`, because the number is in
|
|
the name now.
|
|
|
|
The two sheets are dialogs: `role="dialog" aria-modal="true"`, the player
|
|
sheet named for what is playing, the half sheet reading its own first
|
|
title back out of the DOM so that twenty-seven kinds of sheet need no list
|
|
of names to keep in step. Opening one puts the focus somewhere sensible —
|
|
the player sheet on its Close, the half sheet on its grab handle, which is
|
|
a real button now ("Close this sheet") and the first dismissal a screen
|
|
reader could ever reach; the scrim behind it never was one.
|
|
|
|
A sheet that is down is `inert` and `aria-hidden`. Neither sheet is
|
|
unmounted — they are translated off the bottom of the screen, and the half
|
|
sheet deliberately keeps its last body rendered through the slide down —
|
|
so before this the closed sheets' rows, the hidden mini bar and the nav
|
|
under an open sheet were all still in the accessibility tree, and TalkBack
|
|
could swipe into every one of them.
|
|
|
|
There is one live region, `.sr-live`, mounted for the life of the app and
|
|
clipped to a single pixel, because a region that appears with its words
|
|
already inside it is announced reliably by nobody; an announcement here is
|
|
a change of text in a node that was always there. That is what carries an
|
|
error and a notice, so an Undo offer is actually read out — and the Undo
|
|
button itself stays reachable, only the sentence beside it is hidden from
|
|
the tree so it is not said twice.
|
|
|
|
Artwork that opens the viewer is a control, not decoration. Artwork that
|
|
is decoration carries `alt=""` and every icon is `aria-hidden`, so the
|
|
tree never reads a filename out. The waveform is `role="slider"` with a
|
|
value and arrow keys where it can seek, and `aria-hidden` on the mini bar
|
|
where it is only a picture of the position. Switches say on or off, choice
|
|
chips say pressed, and the two long descriptions and the gap line say
|
|
expanded.
|
|
|
|
The check, so this does not quietly rot: the walk's probe sweeps every
|
|
interactive element in the live DOM and counts four things — the ones with
|
|
no accessible name (`a11yAnon`, with `a11yWho` naming the first three
|
|
offenders so one run tells you what to add), the ones whose name is junk
|
|
(`a11yBad`: bare digits, a filename, a lone glyph, an essay), the ones
|
|
sitting in a layer that is off-screen but still in the tree (`a11yGhost`)
|
|
and the ones that look chosen without saying so (`a11yState`). All four
|
|
are asserted at zero on Home, the library, a record, a catalog record, the
|
|
artist page, You, the taste page, a half sheet, the player sheet and the
|
|
viewer — and the anonymous count on a room and on both shapes of prompt
|
|
besides, because a room's message box and the prompt's own field are where
|
|
the fields this round finally named actually live: assert it only where
|
|
they are not and the round guards everything except its own work.
|
|
|
|
One known exception, left alone on purpose: the per-row ⋯ is a
|
|
`role="button"` inside the row's own `<button>`, and the mini bar's three
|
|
transport buttons sit inside its `role="button"` the same way. That is
|
|
invalid ARIA, and both ends are named so nothing is anonymous; unpicking
|
|
it means splitting `.trk` (one flex row with a whole-row `:active`) and
|
|
rewriting the walk's `.trk .r` selectors, for no gain a screen reader
|
|
would notice.
|
|
|