Announcing Detail Panel Updates
Permalink to "Announcing Detail Panel Updates"In many master-detail layouts, moving through the list updates the detail pane immediately. Sighted users glance right to see the record. Screen reader users stay in the list and hear only the row — which may be enough, or may omit exactly the field they are scanning for. Announcing the detail on every change sounds like the fix, but read naively it doubles the speech on every arrow press and drowns the list.
This guide covers what, when and how to announce. It belongs to master-detail & split views and complements focus handoff in master-detail layouts.
Spec reference
Permalink to "Spec reference"- SC 4.1.3 Status Messages (AA) — a detail pane updating out of focus is a change of content. Whether it counts as a “status message” depends on whether it reports something the user needs; a full record does not, a key status (“Overdue, 12 days”) might.
- SC 1.3.1 Info and Relationships (A) — a summary tied to a row via
aria-describedbyis programmatic and on demand. - SC 2.2.4 Interruptions (AAA) — announcements users cannot postpone are interruptions; keeping them short and debounced respects the spirit even at AA.
The detail pane itself should be a labelled region (section with aria-labelledby) so users can jump to it with landmark or region navigation when they want the full record.
When to use — and when not to
Permalink to "When to use — and when not to"Announce nothing when the list row already contains what users scan for — name, status, amount — and the detail holds secondary information. Region navigation to the pane is enough.
Add a summary when the decisive information lives only in the detail: an approval queue where the list shows names but the detail shows risk scores, or a ticket list where the detail shows the latest reply. Prefer aria-describedby on the row, which is read after the row when the user pauses (most readers) and costs nothing when they keep arrowing. Use a debounced live region only if descriptions are not read reliably by your users’ readers.
Never pipe the full pane into a live region. The misapplication shows up as screen reader users hearing ten fields after every arrow press, or switching the feature off entirely.
Annotated code example
Permalink to "Annotated code example"<ul role="listbox" aria-label="Approval queue" aria-describedby="queue-help">
<!-- Summary of the detail attached to the option (SC 1.3.1) -->
<li role="option" id="r-17" aria-selected="true" aria-describedby="sum-17" tabindex="0">
Lund & Co — Expense report
<span id="sum-17" class="visually-hidden">Risk high. 3 policy issues. Submitted 2 days ago.</span>
</li>
</ul>
<!-- Pane is a labelled region users can navigate to (SC 1.3.1) -->
<section class="detail" aria-labelledby="detail-h">
<h2 id="detail-h" tabindex="-1">Lund & Co — Expense report</h2>
…
</section>
// Fallback: debounced live summary for readers that do not read descriptions in listboxes
let t;
list.addEventListener('keydown', () => {
clearTimeout(t);
t = setTimeout(() => {
const id = activeOption().id;
status.textContent = summaryFor(id); // one line, not the pane (SC 4.1.3)
}, 700); // only after the user pauses
});
Keyboard & AT behaviour
Permalink to "Keyboard & AT behaviour"| Event | Expected announcement | AT deviations |
|---|---|---|
| Arrow to an option | “Lund & Co — Expense report, 3 of 40” then, after a pause, “Risk high. 3 policy issues…” | NVDA reads descriptions after a short delay; JAWS depends on verbosity settings |
| Rapid arrowing | Only option names; descriptions skipped | — |
| Region navigation (D in NVDA, R in JAWS) | “Lund & Co — Expense report, region” | VoiceOver uses the rotor’s landmarks list |
| Enter | Focus to detail heading | — |
Integration context
Permalink to "Integration context"The list role choice affects description support — see listbox versus grid for selectable record lists. Summary wording follows the same principles as aria-describedby for column help text. If you use a live fallback, keep it in the same queue as other messages, as in announcement queues for competing messages.
Gotchas
Permalink to "Gotchas"Descriptions that duplicate the name. If the summary repeats the row text, users hear everything twice. Include only what the row lacks.
Long descriptions. Descriptions are read in full. Keep them under about fifteen words; point to the pane for the rest.
Asynchronous detail loading. If the detail loads from the server after selection, the summary may not exist yet. Show “Loading details” visually and do not announce until it arrives — and then only if the user has paused on that row.
Framework notes
Permalink to "Framework notes"React Aria ListBox and GridList accept a description slot per item that wires aria-describedby for you. Angular CDK cdkListbox options are plain elements — add the description span and ID yourself. In Vue with headless libraries such as Headless UI, the option render slot can include the hidden summary; generate IDs with useId() (Vue 3.5+).
// React Aria Components
<ListBoxItem id={r.id} textValue={r.title}>
<Text slot="label">{r.title}</Text>
<Text slot="description" className="visually-hidden">{r.summary}</Text>
</ListBoxItem>
Testing checklist
Permalink to "Testing checklist"Design system notes
Permalink to "Design system notes"Let list components accept a summary per item and decide centrally whether to render it as a description or as a debounced announcement. Products supply the data; the component guarantees length limits and timing.
FAQ
Permalink to "FAQ"Is it a WCAG failure if the detail pane updates silently?
Generally no — the user can navigate to it, and the row is announced. It becomes a problem when critical information, such as a warning, appears only in the pane.
Should warnings in the detail be announced?
Yes, if they matter for the decision the user is making in the list. Put them in the row’s description or, for severe cases, in the row text itself.
Polite or assertive for the fallback summary?
Polite. It describes what the user is looking at, not an urgent event.
Can I use aria-details instead of aria-describedby?
aria-details points to rich content without reading it; support is limited and users must invoke a command to reach it. It is fine as an addition but not as the main mechanism.
How do I decide which fields go into the summary?
Ask what users decide in the list. In an approval queue it is risk and amount; in a support queue, priority and last reply; in a log viewer, severity. Interview or observe users, pick the two or three fields that drive the decision, and leave everything else in the pane.
Should the summary be visible as well?
Often yes. If a field matters enough to announce, sighted users benefit from seeing it in the list too — and then the summary may become unnecessary because the row itself carries the field.
Related
Permalink to "Related"- Focus handoff — when focus should move instead
- Listbox versus grid — the list’s role
- Verbosity settings for data announcements — letting users choose