htmlaccessibilitywai-ariascreen-readers

How to annotate ARIA grid HTML table when a selection change of a cell causes opening a menu


I have a role="grid" table with some cells sharing the same content (e.g. text, number or date).

enter image description here

Clicking a cell means changing the selected state of the value in the cell, which is visually displayed by a different border color around the cell. This selection can also be controlled via keyboard (e.g. Control + Space) as described for the ARIA grid pattern.

When a cell (actually it's value) is selected, along with it, all other cells with the same value are also selected.

All selected cells get set the attribute aria-selected="true" (false if not selected).

When toggling the selection of a cell (its value) the backend is asked via AJAX request to confirm this and provide some actions. While waiting the cursor is changed to wait on the table.

When the actions arrive from the backend, a popup menu is opened and visually attached to the last clicked cell.

What ARIA attributes must I add to the cells also?

Corresponding questions:


Solution

  • Good question, it’s great that you are looking into proper use of ARIA!

    You’re on a good track with your questions, I’m just afraid that there is a hick-up with the use of selection to trigger an action, which impedes correct use of aria attributes. This is reflected in your first question:

    Is aria-haspopup="menu" fine and compatible with aria-selected="true" change?

    No, a change of aria-selected is not expected to change aria-expanded. That might not be explicitly documented, but is a convention:

    Selecting items usually is a manual, intermediary step for the user, before executing an action on that selection. Selecting items shouldn’t trigger anything, especially not changing the set of selected items. That’s unexpected.

    Case in point: to my knowledge, assistive technologies have no mechanism to communicate to the user what other cells have been auto-selected, as the state change would only be announced for the grid cell under focus.

    Simplify the interaction with an action rather than a selection

    My recommendation here would be to work with an action on the value, rather than a selection.

    Activating the item would open the menu, and we can find good orientation on the Menu Button Pattern, including the use of aria-haspopup and aria-expanded.

    While it would be possible to use the cell itself as the triggering element (<td aria-haspopup="menu">), I’d recommend the use of a button within the cell to make it more obivous.

    In the end, anything discoverable by means of ARIA attributes, should also be made obvious visually and for users of pointer devices. Clicking a cell is not expected.

    This, then, raises the question Whether to Focus on a Cell Or an Element Inside It. The APG mention:

    A cell contains one widget whose operation does not require arrow keys and grid navigation keys set focus on that widget. Examples of such widgets include […] button […]

    <td><button aria-expanded="false" aria-haspopup="menu" tabindex="-1">Germany</button></td>
    

    So you should make sure focus is set on the button with the arrow keys, rather than the cell.

    Provide a hint on the affected rows

    The selected state currently helps the user determine which rows will be affected by the actions.

    If a visual hint is enough, you could add a style to highlight these rows.

    <td class="highlight"><button …>Germany</button></td>
    

    If more guidance is necessary to prevent mistakes, you might want to consider these to options:

    Deal with backend responses

    What if the backend decides that no actions are available and so no menu is shown?

    If the backend cannot deliver the information whether actions are available for a country along with the data for the grid, you should still open the pop-up, because feedback to the user’s action is always necessary (within 150 ms), a change to aria-expanded="true" is expected.

    Do I need aria-expanded and aria-controls?

    You must use the former, and should use the latter, but only once the pop-up becomes visible.

    Do I need to indicate the loading state of the menu somehow (waiting for backend's actions)?

    Visibility of system state is important, so while waiting for the response, you would show a loading indicator within the menu pop-up, and set focus on the menu, which can provide the loading state in its name for assistive technology.

    To summarise:

    1. Open the menu pop-up, set aria-expanded="true" and aria-controls on the button.

    2. Set focus to the empty menu, with a loading animation.

    3. When the backend response arrives, insert the delivered menu items and change the pop-up’s name.

    4. Set focus to the first new item. If the result is empty, provide a disabled menu item stating so.

    and then

    <ul aria-label="Actions for Germany" role="menu" aria-busy="false">
      <li role="menuitem" aria-disabled="true">No actions available</li>
    </ul>
    

    The use of aria-busy here is optional, it doesn’t have much support currently, and if the actions arrive in one response, it doesn’t change much whether the empty contents are announced before.

    The popup exists at first when we get the actions from backend. Do I set aria-expanded="true" at first when getting the response?

    Visibility of the pop-up and the ARIA state must be set together. You might not show the pop-up while loading, but showing system status then would be difficult.

    Correct key binding to select cells

    The APG actually mention that

    Control + Space: selects the column that contains the focus.

    (emphasise mine)

    but the Grid pattern doesn’t mention how one would select a single cell. One needs to dive into the practices of Developing a Keyboard Interface to find the answer:

    When selection does not follow focus, the user changes which element is selected by pressing the Enter or Space key.