I am creating a React component for tables with expandable rows, and I want to make it as accessible as possible.
Here's a simple, unstyled example of what I'm making:
https://codesandbox.io/s/nz8r2w74j
Whenever I click the "more info" button, a new row is added, with info about the row in front of it.
What do I need to add in terms of wai-aria roles, focus management and other stuff in order to make it truly accessible?
You essentially have a "disclosure widget".  The button that opens/closes the section would have aria-expanded set to true/false.
However, I would not literally add a new row to the table because that might confuse screen readers. When the table is first navigated to, the user will hear the table has four rows (including the header) and four columns. When you click the "more info" button, the table will now have five rows but the screen reader is not going to tell the user that another row appeared. If the user was navigating down the column and hearing the row numbers (which are normally announced by screen readers), they'd end up on row five when earlier they heard there were only four rows in the table.
I don't know if this would work for your case, but in the demo code, the extra info is related to the person so it could just be hidden information (css display:none) that exists in the first table cell. When you select the button, the information is revealed (css display:block).
Also, you would either need to make the name a row header (<th scope="row">) or you'd need to associate the person's name with the "more info" button so that the screen reader knows which person they're getting more info about.
I don't know react but the generated html would either look like this (with row headers):
<tr>
  <th scope="row">Avicii</th>
  <td>Progressive House</td>
  <td>πΈπͺ</td>
  <td>
    <button>More info</button>
  </td>
</tr>
<tr>
  <th scope="row">Kygo</th>
  <td>Tropical House</td>
  <td>π³π΄</td>
  <td>
    <button>More info</button>
  </td>
</tr>
or would look like this (with additional information associated with the button):
<span id="moreInfoID" class="sr-only">more info about </span>
...
<tr>
  <td id="name1">Avicii</td>
  <td>Progressive House</td>
  <td>πΈπͺ</td>
  <td>
    <button aria-labelledby="moreInfoID name1">More info</button>
  </td>
</tr>
<tr>
  <td id="name2">Kygo</td>
  <td>Tropical House</td>
  <td>π³π΄</td>
  <td>
    <button aria-labelledby="moreInfoID name2">More info</button>
  </td>
</tr>
The latter is a bit more work. I would recommend the first one.
(You can see info on the sr-only class at What is sr-only in Bootstrap 3?).
Also, your example shows the new row added has tabindex="0".  Since the new information is not an interactive object, it should not receive keyboard focus and shouldn't have tabindex.
You could add aria-expanded="true" to the button when the collapsible section is expanded. And if you have tabindex="0" on the focusabled items in the table (whole table), you wouldn't worry about tab ordering. 
I've updated the sandbox: https://codesandbox.io/s/k5pkj4wzw3
For further reading on accessible collapsible sections (read: expandables), I recommend this article: https://inclusive-components.design/collapsible-sections/
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With