How to build an accessible ContainedList in React
The container heading labels the ul/li structure; interactive rows must slot a real button or link via asChild so role and focus are native, not faked on a div
When to use a ContainedList
- Grouping a short set of related rows under a visible heading in a bordered surface
- Presenting selectable or navigable rows (settings groups, member lists)
- Separating a labelled cluster of items from surrounding page content
When not to use it
- A long, virtualised data set — use a Table or DataList instead
- Plain bulleted prose where the container border adds no meaning — use List
Keyboard interactions
Role list, verified at WCAG 2.2-AA.
TabEnterSpace
Common mistakes
Avoid: Putting interactive controls on a plain ContainedListItem div
Prefer: Use ContainedListItem asChild with a <button> or <a> so the row is keyboard-focusable
A non-interactive div gives no focus or role semantics to assistive tech
Example
<ContainedList label="Members">
<ContainedListItem>Ada Lovelace</ContainedListItem>
<ContainedListItem>Alan Turing</ContainedListItem>
</ContainedList>