I’m trying to make a list accessible using role="list"
as the parent and role="listitem"
for the items. I want each list item to have a description using aria-describedby
in addition to its text content.
Here is a simplified version of my code:
<div class="wrapper">
<div id="rbd-hidden-text-11-hidden-text-132" style={{ display: "none" }}>
This text should be read by screen reader
</div>
<div role="list" style={listStyle}>
{items.map((item, index) => (
<div
key={index}
// NOTE: using listitem, you can focus item's focusable
// children like buttons but aria-describedby is not read on
// macOS
role="listitem"
// Button role makes aria-describedby readable by macOS VO
// but you cannot focus its focusable children :(
// role="button"
style={listItemStyle}
tabIndex={0}
// macOS reads this only when role="button"
aria-describedby="rbd-hidden-text-11-hidden-text-132"
// aria-labelledby="rbd-hidden-text-11-hidden-text-132"
// aria-description="Is this read by a screen reader?"
>
{item}
<button>Action1</button>
<button>Action2</button>
</div>
))}
</div>
</div>
When testing on macOS Chrome, everything works fine. When a list item is focused by VoiceOver, the description is read as expected. However, this does not work on Safari.
Changing the role
to button
makes aria-describedby
readable by VoiceOver on macOS, but introduces another issue: elements with role="button"
prevent VoiceOver from focusing on interactive children.
My Questions:
- How can I get
aria-describedby
to work withrole="listitem"
on Safari with VoiceOver? - Is there a workaround to make
aria-describedby
work without changing the role tobutton
and still allowing interactive children to be focused?
Any help or suggestions would be greatly appreciated!
CodeSandbox demo