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
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:
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
There are two potential DOM structures for secondary actions in composite widgets. Using tablist
roles as an example (and excluding non-relevant attributes):
<div role="tablist">
<div role="tab">
Item 1
<button>secondary action</button>
</div>
</div>
Problems:
- The
tab
role hasChildren 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"
<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
- 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.
tree
andgrid
. - Enable an accessible semantic mapping for new patterns like Open UI's
selectmenu
that may contain nested interactive elements. - Potentially enable custom screen reader actions UI, as mentioned in this comment: w3c/aria#762 (comment)
- Create an
aria-actions
attribute that accepts a space-separated list ofid
s pointing at related interactive controls. - (Potential action): remove "Children Presentational" from
menuitemcheckbox
,menuitemradio
,tab
, andoption
in the ARIA spec - (Potential addition): referenced secondary actions should have
aria-controls
pointing back at theid
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.
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
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
- 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.
In step 2.F.iii, if the current node
has aria-actions
and one of the aria-actions
id
s 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-actions
by 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-actions
API mappings by default for nested interactive items in new proposed composite widget elements likeselectmenu
.
Good point ๐. How would you feel about this?
I'm mostly wordsmithing b/c conventional or discoverable seems a bit hard to translate to specifics to me. Maybe there could be an additional
SHOULD
around discoverability?Another good example might be tabs with close buttons using
ctrl + w
to close instead of adding the close button to the tab order.