Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve accessibility of support search components #43617

Closed
getdave opened this issue Jun 24, 2020 · 10 comments · Fixed by #43963
Closed

Improve accessibility of support search components #43617

getdave opened this issue Jun 24, 2020 · 10 comments · Fixed by #43963
Assignees
Labels

Comments

@getdave
Copy link
Contributor

getdave commented Jun 24, 2020

Currently, the support search components are not fully accessible to users of AT. This is because they:

  • don't implement ARIA roles.
  • rely too heavily on visual cues to indicate state.
  • don't fully support keyboard interactions (rover tab index...etc)

Some specific issues:

  • nothing to indicate a relationship between the search input and the search results
  • nothing to indicate the active/selected search result
  • no indications/notifications as to the various states of "searching" (eg: loading, no results, results found...etc) - should use 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:

  • which Reakit components we could put to use here.
  • any existing examples we could copy/learn from
  • any specific ARIA roles/patterns we might like to consider.

The component we are referring to is:

Screenshot 2020-06-24 at 12 03 59

@diegohaz
Copy link
Contributor

  • 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: WordPress/gutenberg#19657

And this excellent comment by @jeryj that definitely worth checking: WordPress/gutenberg#19657 (comment)

@jeryj
Copy link
Contributor

jeryj commented Jun 29, 2020

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:

  • Implement WAI-ARIA 1.2 combobox markup
  • Remove the search result links from being tabbable (tabindex=-1, since they're links)
  • Remove the title attribute from the search results

@getdave
Copy link
Contributor Author

getdave commented Jun 29, 2020

Thanks 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?

@jeryj
Copy link
Contributor

jeryj commented Jul 2, 2020

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:

Support search section on /home

  • Use 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.
  • "Get help" title shouldn't be an 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.
  • Announce loading state
  • Announce results from search
  • Search icon in input announces "Open search, button". I think this icon could be hidden as it is decorative or the button role could be removed and the aria-label changed. I'm not sure why it's a button currently, as its unfocusable.
  • X button to clear search announces "Close search, button" instead of "Clear search, button"
  • Remove title attributes from links. It's best to avoid title attributes in general.
  • Should 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?

? FAB

  • Pressing Help Questionmark should move focus to the popover or search input
  • Go straight to the full article dialog on click. The "between" state of selecting a link, then being brought to a summary (the "between" state) could be removed, IMO. I think selecting a link should go straight to the dialog like the Home search. This "between" state feels like a confirmation: "Did you really want to read that article?"
  • Focus loss on closing the full article dialog as the FAB popover has been closed

If the "between" state isn't removed, these additional items would need fixed

  • After selecting a link, and then pressing "< Back" it should return focus to the link that activated it
  • Announce the new content

Possibly pedantic distracting discussion. Feel free to ignore 😅

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?

@jeryj
Copy link
Contributor

jeryj commented Jul 6, 2020

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:

1. Should this use component arrow key navigation?

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:

  • Allows you to section results
  • Uses aria-live to announce new results
  • TAB to move between links
  • Heading shortcuts on a screen reader to jump between sections

Implementation 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

2. If we keep arrow-key navigation and go with a combobox then...

  • We're diverting from the combobox selection on enter (not too big of a deal)
  • A combobox controls a listbox, which has options that are not supposed to contain interactive roles. i.e., you're not supposed to have a <div role="option"><a href=...></a></div> since the <a> is an interactive element.
  • VoiceOver in Safari isn't announcing items in a listbox correctly. Maybe this is something new or only effecting my computer.
  • The implementation looks like it could be a bit tricky to add things to the Search component (aria-activedescendent, ids in the list items, etc). @getdave likely has better opinions than I on this matter.

3. We could use arrow-key navigation with a less-prescriptive role.

  • Basically option 1 above but adding tabindex="-1" to the links and preserving the current arrow key interactions.
  • Maybe add an 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

@frontdevde
Copy link
Contributor

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.

@diegohaz
Copy link
Contributor

diegohaz commented Jul 7, 2020

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 (WordPress/gutenberg#21080 (comment)), where normally the block list uses the grid pattern, but, when interacting with the search box, it's replaced by a combobox grid:

Screenshot exemplifying the statement above

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.

@jeryj
Copy link
Contributor

jeryj commented Jul 7, 2020

After discussing a bit more with @diegohaz, we've put together some clearer direction for how the markup and interactions should work.

Overview

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.

Markup General Structure

    <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>

Keyboard interactions

  • Tabstop: Search input
  • Tabstop: Search Results section 1, first item with roving tabindex on each gridcell.
  • Arrow Up/Down: Move to previous/next search result. If at the bottom of the first section, an arrow down press would not do anything.
  • Tabstop: Search Results section 2, first item with roving tabindex. Same arrow key interactions as first section.

Other Interactions

  1. Use speak() to announce state changes on the search, such as:
  • Loading/Searching
  • New results loaded
  • Errors

@jeryj
Copy link
Contributor

jeryj commented Jul 9, 2020

After working on implementing this in #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:

  • Saves a maximum of 6 keypresses for sighted keyboard users :tab is not a primary form of navigation for screen readers

The cons:

  • Increased complexity of markup and code
  • Semantics are worse: The screen reader announcements are more verbose, including information about columns that are irrelevant here.
  • Interaction may be confusing: Tab to reach each support, arrow keys within it)

@jeryj
Copy link
Contributor

jeryj commented Jul 13, 2020

Read an article this weekend from Adrian Roselli on ARIA Grid as an Anti-Pattern which supports leaving the links as normal TAB links.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
5 participants