Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@smhigley
Last active April 14, 2022 17:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save smhigley/8dbe67f834cc472e3a14bf6b289e6f0c to your computer and use it in GitHub Desktop.
Save smhigley/8dbe67f834cc472e3a14bf6b289e6f0c to your computer and use it in GitHub Desktop.
Secondary Actions Proposal

Secondary Actions Proposal

This is a both an explainer for why a secondary actions proposal is needed, and a draft of the proposed change to the ARIA spec.

Original issue: w3c/aria#1440

Jump straight to the Proposal

What are secondary actions?

Secondary actions are, as the name implies, additional interactive items that are related to one primary interactive control within a composite widget. This proposal specifically concerns interactive children of these roles:

  • combobox
  • grid
  • listbox
  • menu
  • menubar
  • tablist
  • tree
  • treegrid

This pattern is increasingly common in the wild. Here are some real-world examples of secondary actions on a tab button, a menu item, and a tree item:

the VS Code tab list of open files, the selected tab has a visible close button A single item from within a menu or other interactive list; the item has an icon, a formatted name (Document125) and file location, then at the right there are three icon buttons for share, star, and a kebab menu A part of the Teams meeting UI, showing only the first meeting participant under the tree section titled "In this meeting". The participant tree item shows a small avatar, a name, and to the right are a mute button and kebab menu

While compound widget roles have the most immediate need for secondary action semantics, the pattern could also apply to a range of other control types. Some examples include:

  • The menu button in a splitbutton
  • a dialog with a close action

Challenges in authoring secondary action patterns today

There are two potential DOM structures for secondary actions in composite widgets. Using tablist roles as an example (and excluding non-relevant attributes):

1. Child actions

<div role="tablist">
  <div role="tab">
    Item 1
    <button>secondary action</button>
  </div>
</div>

Problems:

  • The tab role has Children presentational: true, meaning it strips the semantics from any child elements. Per the spec, the child button should not be exposed as a button, causing it to be undiscoverable by screen reader virtual cursor, and causing inconsistencies when focus lands on it.
  • The calculated name for the tab button would be "Item 1 secondary action" instead of "Item 1"

2. Sibling actions

<div role="tablist">
  <div role="tab">Item 1</div>
  <button>secondary action</button>
</div>

Problems:

  • While the spec is ambiguous about whether buttons can be descendants of a tablist (ref: w3c/aria#1454), it isn't explicitly allowed and creates inconsistencies in practice (e.g. numbering of items in the tablist, screen reader mode switching when focus is on the button).
  • The "Item 1" tab button and the secondary action are not clearly associated.
  • Likely less intuitive for authors
  • usually requires an extra wrapping node for styling/layout

General problems with both approaches

  • There is no consistent way to expose the existence of related secondary actions without including them in the accessible name, which is verbose and repetitive.
  • While nested secondary actions have more practical issues in screen readers today, miscellaneous sibling interactive items also don't have perfect support. (testing results: https://a11y-screenreader-demos.netlify.app/studies/secondary-actions/)

Goals

These are the functional needs that a spec solution to secondary actions would ideally fulfill:

  1. Support both child and sibling secondary action markup patterns.
  2. Surface the existence of secondary actions to screen reader users when focus/virtual cursor is on the primary interactive element.
  3. Exclude secondary actions from the primary action's accessible name when they are nested.
  4. Solve #2 and #3 for patterns that currently allow nested interactive items, e.g. tree and grid.
  5. Enable an accessible semantic mapping for new patterns like Open UI's selectmenu that may contain nested interactive elements.
  6. Potentially enable custom screen reader actions UI, as mentioned in this comment: w3c/aria#762 (comment)

Proposal

  1. Create an aria-actions attribute that accepts a space-separated list of ids pointing at related interactive controls.
  2. (Potential action): remove "Children Presentational" from menuitemcheckbox, menuitemradio, tab, and option in the ARIA spec
  3. (Potential addition): referenced secondary actions should have aria-controls pointing back at the id of the primary action.

Removing "children presentational" from composite widget child roles that don't allow it has both pros and cons. Including the child actions in the accessibility tree would improve virtual cursor access for screen readers with a virtual cursor, but would potentially add a large number of very repetitive buttons/links/etc to the accessibility tree in the case of long sets of items that each have the same action or actions.

Preserving the current "children presentational" semantics could work, provided child secondary actions have their semantics exposed when focused. The downside is that screen readers would either need to develop their own UI to activate secondary actions from the primary action (similar to VoiceOver's actions menu), or users would need to rely on the authored keyboard interaction to access them.

Scope of roles that allow aria-actions:

There are multiple options for defining allowed roles for aria-actions, ranging from least permissive to most permissive:

  • children of composite widget roles
  • all widget roles
  • all nameable roles (i.e. excluding roles with name prohibited)
  • all roles excluding generic

The benefit of a more permissive set of allowed roles is that it enables authors to accessibly mark up complex UI beyond what we've actively thought of in this proposal, or beyond what exists today.

The primary drawbacks are that it introduces more potential for unforseen complications, and more potential for misuse to become widespread enough that screen readers drop support.

One note in support of the "all nameable roles": this captures the set of roles that are individually reachable by AT without limiting authors. As an example, if an author wished to

Scope of roles that allow reference by aria-actions:

There are also a couple options for limiting (or not limiting) the scope of what can be referenced with aria-actions. As a general approach to limiting allowed referenced elements, targeting nameable, focusable roles seems most logical. Some variations of that include:

  • All widget roles
  • All widget roles apart from composite widget roles (this would still allow their children, e.g. menuitem, to be referenced)
  • Any element that supports an accessible name and is focusable or has a click action

Authoring requirements for aria-actions:

  • The referenced controls MUST exist in the DOM
  • Authors MUST provide a keyboard mechanism to navigate to or directly activate the secondary actions.
  • If the secondary action is not directly navigable with the keyboard and author provides a keyboard shortcut to directly activate it, that shortcut SHOULD be discoverable and follow existing conventions.

Accessible name calculation change:

In step 2.F.iii, if the current node has aria-actions and one of the aria-actions ids matches the child node's id, skip steps a-c for this child.

Next steps

If this mechanism gets support, we would need to:

  1. Determine Accessibility API mappings for aria-actions (this would likely be the general ARIA bucket API prop)
  2. Contact screen reader vendors to determine appetite to support aria-actions by surfacing some sort of "actions available" announcement, and improving support for nested interactive items.
  3. Work with browser vendors and Open UI to implement the aria-actions API mappings by default for nested interactive items in new proposed composite widget elements like selectmenu.
@smhigley
Copy link
Author

Link to a comment with specific suggested spec wording: w3c/aria#1440 (comment)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment