The purpose of this gist is not to directly recommend a specific implementation of a selectmenu
element, but instead to lay out how different variations in content will affect the semantics and keyboard handling needed to make it accessible.
Secondary actions refers to when individual options have actions that may be taken in addition to the primary selection action:
These additional actions must fulfill all of the following criteria:
- Each action is associated with one and only one specific option.
- Each action is a single focusable element -- for example a menu cannot be a secondary action, but individual menuitems could be.
- The actions are always present in the DOM
These would then ideally be surfaced by screen readers when interacting with the option with a cue like "actions available" or "3 actions available." The selectmenu itself would need to handle keyboard access to the additional actions, likely with left/right arrows moving between the actions and primary option, and up/down arrows always moving to the previous or next option.
Based on the ARIA Secondary actions proposal, the markup would look similar to this if it were marked up using ARIA attributes:
<button role="combobox" aria-expanded="true" aria-controls="popup" aria-haspopup="listbox" aria-activedescendant="option1">
<div role="listbox" id="popup">
<div role="option" id="option1" aria-actions="option1-pin">
Apple
<button id="option1-pin>Pin</button>
</div>
<div role="option" id="option2" aria-actions="option2-pin">
Banana
<button id="option2-pin>Pin</button>
</div>
<div role="option" id="option3">Cherry</div>
</div>
Instead of having secondary actions that are associated with specific options, this variation deals with including top-level actions or controls that are within the popup but outside of the listbox/set of options.
The emoji picker shows a tab control, search input, and gif search link in addition to the selectable emojis themselves.
This datepicker implementation has buttons to move between months or years, or go to today's date
This is where the semantics of the popup would change from a listbox
to a dialog
, and it would likely send focus within the popup when it opens, and trap tab focus with tabbing moving between the listbox and the additional controls.
As a listbox pattern is a long-understood construct, the inclusion of the additional buttons before and after the listbox would not be as discoverable were they to just be 'included'. Buttons within a listbox can also add more concrete accessibility bugs, e.g. with unwanted mode switching on Windows screen readers, or interfering with position and size of set calculations. However, by including a parent role=dialog as the popup container, this moves the buttons out of the listbox and helps set the user expectation that this popup likely contains a variety of controls.
A simplified example might have these semantics:
<button role="combobox" aria-expanded="true" aria-controls="popup" aria-haspopup="dialog">
<div role="dialog" id="popup">
<button>Select All</button>
<div role="listbox">
<div role="option" id="option1">Apple</div>
<div role="option" id="option2">Banana</div>
<div role="option" id="option3">Cherry</div>
</div>
<button>Create New +</button>
<button>Search for more</button>
</div>
There isn't really a good pattern for this. My personal opinion is that this should not be supported. A very determined developer could style a single option to appear as a button, and it would probably be a better end result than the browser providing a lone button within a listbox or splitting the other options into two or more listboxes.
There are essentially three semantic options for making this work:
- Split the options into two or more separate listboxes. This would be the most literal approach, but would create an unexpected keyboard experience, since it would essentially mean users do not arrow between all options -- they would arrow through the first listbox, and then need to tab to reach the second set of options.
- Drop a semantic
button
(or other control) inside a listbox. This creates a few problems with screen reader experience: buttons, links, and other singular controls trigger mode switching in Windows screen readers, and it has the potential to change the calculation of index and max count for the surrounding options. - Do not provide support for the first two options, and let authors style and treat options as buttons or links. There's no way to prevent this anyway, and it may be the best solution.
A grid layout of options doesn't necessarily require grid semantics, if the layout is purely for visual presentation, and the items still have linear relationships with eachother. This should be achievable only with CSS without any negative accessibility impact.
These colors have row and column relationships, so unlike the earlier colorpicker, grid semantics do make sense here.
If the items within the dropdown have more complex relationships, there's likely no way to alter the standard list-like selectmenu to fit the different semantic and interaction requirements. The keyboard interaction to move between selectable items would be different for each, as would the mechanism to access any secondary actions (since left/right arrows are already used to navigate the base control).
It would theoretically be possible to create a dialog combobox and put a grid or tree within it, but unless there is a separate reason to need a dialog (e.g. extra month/year buttons in a datepicker), the experience wouldn't be ideal in editable combobox scenarios. It's not possible to keep keyboard focus within the text input while interacting with controls in a dialog, since the user needs to be able to tab through an unknown number of controls within the dialog. For non-editable scenarios it likely wouldn't matter as much, but trapping focus within a dialog with a single tab stop might be unintuitive.
Per example 1, instead of just pointing to the secondary actions proposal, include a bit of information here as to examples of how this could work. E.g., how might these actions be surfaced to someone? Via an announcement saying "actions available" and then a user can use right/left arrow keys to cycle through available actions individually and then press enter to confirm?
would add after "... moving between the listbox and the additional controls."
regarding example 3, i'm not exactly sure the use case at this point? Maybe the image placeholder would help. Point 2 here is really important though, and something that NVDA/JAWS would specifically have to change so as to not pop someone in and out of scan/forms mode. Each time this comes up in a conversation (including links/buttons inside of composite widgets that have have decades of being interacted with in forms-mode alone) I have wondered how to broach this subject without putting everyone to sleep (more so than i likely already do). AT would need to change here for these patterns and that would be a slow process in getting into the hands of people that would be most likely to be confused by this change.
Re: point three. You're right. It potentially gets rather confusing when you have options that serve to make a selection, and then other options which perform an action. Adds some extra cognitive load to remember the organizational pattern and what the context for a particular action is, when it's x focus stops away from the actual option that gave it context. E.g., [option name] [action 1] [action 2] [action 3] [action what-was-this-4-again?]