Currently, the support search components are not fully accessible to users of AT. This is because they:
Some specific issues:
input
and the search _results_wp.speak()
or similar.Many of these issues could be solved by making use of Reakit by the excellent @diegohaz.
@diegohaz if you have time, I'd really appreciate some guidance on the best route forward in terms of:
The component we are referring to is:
- any specific ARIA roles/patterns we might like to consider.
That's definitely a combobox
widget.
- which Reakit components we could put to use here.
- any existing examples we could copy/learn from
According to the WAI-ARIA docs, a combobox
is a subclass of select
, which is, in turn, a subclass of composite
. Reakit has an abstract Composite component that can be used for that. Although it still requires the specific implementation and aria props. There's an example here: https://codesandbox.io/s/composite-gcqs2?file=/index.js:3117-5243
A specific Combobox
module is in the works though.
There's also this PR on Gutenberg that's adding a Combobox component using Downshift: https://github.com/WordPress/gutenberg/pull/19657
And this excellent comment by @jeryj that definitely worth checking: https://github.com/WordPress/gutenberg/pull/19657#issuecomment-638412385
That's definitely a combobox widget.
I second @diegohaz!
A specific Combobox module is in the works though.
This will be so useful!
It looks like the arrow key interactions are there already. A few things to do based on a very quick review:
combobox
markuptabindex=-1
, since they're links)title
attribute from the search resultsThanks for your input @diegohaz that's great and aligns with my understanding.
I'm not 100% sure. Should we be using Reakit or @wordpress/components
's combobox component in Calypso?
I tested this more in Safari using Voice Over and thought about it more closely. This is a complicated little box! Here are my suggestions:
/home
section
instead of a div
, as it's a standalone section unrelated to the main content. Maybe an aside
. I'm also wondering about if the role="search"
should wrap the entire component or just the search field.h1
unless it's more semantically divided than just being wrapped in a div
. Same for the WordPress App
card below it. Looking at the page structure, an h2
or h3
seems appropriate. button
role could be removed and the aria-label
changed. I'm not sure why it's a button currently, as its unfocusable.title
attributes from links. It's best to avoid title
attributes in general. tabindex=-1
be added to the links? They should not be tabbable in this instance if we go with a combobox
. Or should they be a different element altogether, such as a <li role="button">
so it communicates the states without being focusable by default?Is this a combobox in the end? It's displaying search results based on the search, but a combobox is supposed to set the value of the textbox on selection. In this case, it's an autoloaded search results that _look_ like a combobox. From the ARIA Docs:
"A composite widget containing a single-line textbox and another element, such as a listbox or grid, that can dynamically pop up to help the user set the value of the textbox"
On Enter
of a combobox result, it should set the search to that value. In this instance it takes you to that search result but does not set the textbox. Does this diverge enough that we should _not_ use a combobox
? I think it's important to semantically link the search to the results. Is there a different way we can semantically link the search to the results without labelling it a Combobox?
I spent too much time today digging in on this, and didn't come out with any clearer idea on what the end result should be. Here are my current, foggy thoughts on possible direction for the markup:
I'm not 100% convinced it should. As slick as I think the interaction of a DOM focused input with a virtual focus on the selections, I don't know that it's really applicable in this case. I think this is a search input that dynamically populates a list of results. It's not meant to fill out a form.
If we go with this as a list of links (soon to be divided into sections), then we can use markup like this:
<section>
<label for="search">Search for Help</label>
<input id="search" type="search" aria-controls="search-results" />
<div id="search-results" aria-label="Search Results" aria-live="polite">
<h3 id="section-1">Section 1</h3>
<ul role="group" aria-labelleddby="section-1">
<li><a href="#">Item 1</a></li>
<li><a href="#">Item 2</a></li>
</ul>
<h3 id="section-2">Section 2</h3>
<ul role="group" aria-labelledby="section-2">
<li><a href="#">Item 3</a></li>
<li><a href="#">Item 4</a></li>
</ul>
</div>
</section>
This does a few things:
aria-live
to announce new resultsTAB
to move between linksImplementation of this would be fast. Testing it out locally works fairly well IMO. Here's a non-interactive demo version of that markup: https://codepen.io/jeryj/pen/GRoxKPP
combobox
then...<div role="option"><a href=...></a></div>
since the <a>
is an interactive element.tabindex="-1"
to the links and preserving the current arrow key interactions.role="grid"
or another more generic role that would suggest arrow-key navigation.I'm getting more and more wary of the combobox route since they're already not the most supportive elements, and our use case would further diverge from its original intent. Any thoughts on how we should move forwards?
cc @frontdevde @diegohaz
I'm getting more and more wary of the combobox route since they're already not the most supportive elements
Based on your comment above, I'd tend to agree that our use case has diverged too far for it to be considered a ARIA combobox equivalent (arguably it wasn't in the first place?). Your suggestion for an implementation alternative looks reasonable to me.
After reading @jeryj's comments and thinking more deeply on this widget, I agree that this may not be a combobox. Although the combobox pattern would be useful when the user is interacting with the search box.
The search box and the list of links are, at first, independent from each other. That is, the user could interact directly with the links without ever noticing the search box. And, because of this, I'd expect that a keyboard user could Tab through the links without having to interact with the search box. So, the links should be tabbable, or, at least, be a tab stop independent from the search box by using the grid
pattern as @jeryj suggested.
I'm not sure though how aria-live
on the list element would behave in this situation. Maybe we could just use wp.speak()
to announce the different states as @getdave mentioned. And aria-controls
on the search box seems to be unnecessary here. A role that we may consider using is search
, which, combined with a proper label, would make the widget visible in the landmarks menu for screen reader users:
<section>
<form role="search" aria-label="Search">
<label for="search">Search for Help</label>
<input id="search" type="search" />
</form>
<div>
<h3 id="section-1">Section 1</h3>
<ul role="group" aria-labelleddby="section-1">
<li><a href="#">Item 1</a></li>
<li><a href="#">Item 2</a></li>
</ul>
<h3 id="section-2">Section 2</h3>
<ul role="group" aria-labelledby="section-2">
<li><a href="#">Item 3</a></li>
<li><a href="#">Item 4</a></li>
</ul>
</div>
</section>
When interacting with the search box though, I feel like the combobox pattern would be super useful. It's somehow similar to the interaction model I proposed to the block inserter on Gutenberg (https://github.com/WordPress/gutenberg/issues/21080#issuecomment-649231549), where normally the block list uses the grid pattern, but, when interacting with the search box, it's replaced by a combobox grid:
But the simplest solution that would solve most of the current problems on this component in particular is what @jeryj suggested, without a combobox. So I would go for it for now.
After discussing a bit more with @diegohaz, we've put together some clearer direction for how the markup and interactions should work.
The search input will operate independently of the results. There won't be any arrow key interactions on the results while focused on the search input. Instead, we can use a role="grid"
on each search results section.
This would allow the support search component to take fewer tab stops in the flow and allow fo arrow key interactions on search results.
<section>
<form role="search" aria-label="Search">
<label for="search">Search for Help</label>
<input id="search" type="search" />
</form>
<div aria-label="Search Results">
<h3 id="section-1">Support articles</h3>
<ul role="grid" aria-labelleddby="section-1">
<li role="row"><span role="gridcell" tabindex="0"><a tabindex="-1" href="#">Item 1</a></span></li>
<li role="row"><span role="gridcell" tabindex="-1"><a tabindex="-1" href="#">Item 1</a></span></li>
</ul>
<h3 id="section-2">Show me where to</h3>
<ul role="grid" aria-labelledby="section-2">
<li role="row"><span role="gridcell" tabindex="0"><a tabindex="-1" href="#">Item 3</a></span></li>
<li role="row"><span role="gridcell" tabindex="-1"><a tabindex="-1" href="#">Item 4</a></span></li>
</ul>
</div>
</section>
gridcell
.speak()
to announce state changes on the search, such as:After working on implementing this in https://github.com/Automattic/wp-calypso/pull/43963, I've decided to first go with the simpler <h3><ul></ul>
markup that uses TAB
for everything. The semantics here are clear for both screen readers and sighted users. The grid
markup with arrow keys for navigating between items can be a follow-up issue if we want to.
At the moment, I'm leaning towards _not_ implementing the grid
markup, as here's the full list of pros:
tab
is not a primary form of navigation for screen readersThe cons:
Tab
to reach each support, arrow keys within it)Read an article this weekend from Adrian Roselli on ARIA Grid as an Anti-Pattern which supports leaving the links as normal TAB
links.
Most helpful comment
That's definitely a
combobox
widget.According to the WAI-ARIA docs, a
combobox
is a subclass ofselect
, which is, in turn, a subclass ofcomposite
. Reakit has an abstract Composite component that can be used for that. Although it still requires the specific implementation and aria props. There's an example here: https://codesandbox.io/s/composite-gcqs2?file=/index.js:3117-5243A specific
Combobox
module is in the works though.There's also this PR on Gutenberg that's adding a Combobox component using Downshift: https://github.com/WordPress/gutenberg/pull/19657
And this excellent comment by @jeryj that definitely worth checking: https://github.com/WordPress/gutenberg/pull/19657#issuecomment-638412385