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:
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:
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>
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>
- 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/)
These are the functional needs that a spec solution to secondary actions would ideally fulfill:
- Support both child and sibling secondary action markup patterns.
- Surface the existence of secondary actions to screen reader users when focus/virtual cursor is on the primary interactive element.
- Exclude secondary actions from the primary action's accessible name when they are nested.
- Solve #2 and #3 for patterns that currently allow nested interactive items, e.g.
- Enable an accessible semantic mapping for new patterns like Open UI's
selectmenuthat may contain nested interactive elements.
- Potentially enable custom screen reader actions UI, as mentioned in this comment: w3c/aria#762 (comment)
- Create an
aria-actionsattribute that accepts a space-separated list of
ids pointing at related interactive controls.
- (Potential action): remove "Children Presentational" from
optionin the ARIA spec
- (Potential addition): referenced secondary actions should have
aria-controlspointing back at the
idof 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
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
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
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
- 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
ids matches the child node's
id, skip steps a-c for this child.
If this mechanism gets support, we would need to:
- Determine Accessibility API mappings for
aria-actions(this would likely be the general ARIA bucket API prop)
- Contact screen reader vendors to determine appetite to support
aria-actionsby surfacing some sort of "actions available" announcement, and improving support for nested interactive items.
- Work with browser vendors and Open UI to implement the
aria-actionsAPI mappings by default for nested interactive items in new proposed composite widget elements like