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-describedby is 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.

Three options for detail updates Comparison of announcing nothing, a debounced one-line summary, and an aria-describedby summary on the row, with when each fits. Three options for detail updates✗ Announce nothingBest when the row already has the key fieldsZero extra speechUsers jump to the pane with region navigationRisk: key status hidden✓ Announce or describe a summaryBest when the detail holds the key fieldOne short line per pause or on requestUsers hear the key field without leaving thelistRisk: verbosity if the summary grows

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.

Speech per arrow press Bar chart of approximate seconds of speech per arrow press: the row alone about 2 seconds, row plus a one-line summary about 3.5, row plus the full detail pane about 18. Speech per arrow pressRow onlyname, status, amountRow + summary"Risk high, 3 open issues"Row + full paneten fields everypress
Full-pane announcements make the list unusable.

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 &amp; 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 &amp; 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 —
Whether descriptions on options are read Matrix of NVDA, JAWS, VoiceOver and TalkBack against reading aria-describedby on listbox options, on grid rows, and the debounced live fallback. Whether descriptions on options are readOn listbox optionOn grid rowLive fallbackNVDA + ChromeAfter a pauseAfter a pauseSpokenJAWS + ChromeVerbosity dependentYesSpokenVoiceOver + SafariAfter a pauseInconsistentSpokenTalkBack + ChromeSometimesSometimesSpoken
Descriptions are reliable on most desktop readers; the live fallback covers the rest.

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.

Permalink to "Related"

← Back to Master-Detail & Split Views