Accessible Autocomplete Box

In this post we’ll cover some information and challenges in creating an accessible autocomplete box. A good autocomplete box is accessible by default and will allow all users to navigate intuitively, either by keyboard or mouse. Many of you may have used an autocomplete box before and not even realized that the keyboard shortcuts intuitively used were also there to allow impaired users access to the same functionality.

A challenging task

Building an accessible autocomplete box for the chat was challenging, given our strict set of requirements.

Chat UI showing the autocomplete box when entering the "@" symbol

First, components need to adhere to AA accessibility standards and most libraries really just don’t cut it on this front. We also found some libraries that have too many features that we won’t use. Largely, what many libraries lack is markup structure and correct use of keyboard navigation / focus management. Also, our first implementation of the accessible autocomplete needs to open when the ‘@’ symbol is typed. An autocomplete box that appends inline requires a specific semantic markup structure which we’ll cover later …

Second, our chat input is a textarea and the autocomplete needs to open and append inline to existing text within the textarea value without replacing the whole value. IE: Most autocomplete widgets replace “I’m a big string @ inline” with “@selectedsuggestion.” Instead of “I’m a big string @ inline” with “I’m a big string @selectedsuggestion inline.”

Third, we are slowly phasing out the use of jQuery and implementing newest Javascript as vanilla JS. Doing this will allow us to eventually have a much smaller bundle size and simpler, as well as faster running JS. But this is another article in itself.

Our autocomplete requirements in a nut shell:

  1. Keyboard navigation
  2. Semantic markup and aria attributes
  3. Suggestions append to the input value inline instead of replace the whole input value
  4. No functionality bloat

Markup

We found sourcing this probably the most challenging item in this task, as it was quite hard to decipher the w3 specifications for our requirements. It ended up that the w3 examples are actually quite comprehensive but need to be studied carefully (see authoring practices article).

Stucture

Below you see a basic combobox implementation from w3. We recommend to check role details in more detail on the w3 website, because they share very helpful explanations.

<div aria-label="Tag" role="combobox" aria-expanded="true" aria-owns="owned_listbox" aria-haspopup="listbox">

    <input type="text" aria-autocomplete="list" aria-controls="owned_listbox" aria-activedescendant="selected_option">
</div>

<ul role="listbox" id="owned_listbox">
    <li role="option">Zebra</li>
    <li role="option" id="selected_option">Zoom</li>
</ul>

Needs

So from the example you can see the container needs:

  1. role=“combobox”
  2. aria-expanded=“true/false”
  3. aria-owns=“owned_listbox”
  4. aria-haspopup=“listbox”

The option elements need:

  1. role=“option”
  2. aria-selected=“true/false”
  3. id=“uniqueID”

The input needs:

  1. autocomplete=“off”
  2. aria-controls=“owned_listbox”
  3. aria-activedescendant=“selected_option_unique_id”

Javascript

Given the above markup and aria tags we can then toggle these values with javascript.

Javascript modifies the DOM by setting aria-activedescendant and aria-selected values. Aria-activedescendant represents the selected value in a combobox
Javascript modifies the DOM by setting aria-activedescendant and aria-selected values. Aria-activedescendant represents the selected value in a combobox.

What Javascript is used for

  • On role=“option” – Cycle through aria-selected with keyboard navigation
  • On the options container – Toggle hidden state for suggestions listbox
  • On the input/textarea element – To set the aria-activedesendent

What Keyboard navigation is used for

  • Up / Down – Cycle through suggestions
  • Tab and Shift + tab – Cycle through suggestions
  • Escape – Close suggestions
  • Enter – Choose suggestion and close box

Conclusion

To wrap things up – Seeking out robust accessible markup (from w3) can help give a good starting point when building accessible UI. w3 really is a great source of truth for semantic autocomplete examples. Styling and Javascript can be built on top of any semantic markup. We hope this helps other people out there with their own tricky accessible implementations.