algolia / algolia/docsearch

Accessibility issues with v3 dialog

Open
#1,370 6 comments 10 reactions 0 assignees View on GitHub
Dominant language
TypeScript
Stars
4.4k
Forks
439
Avg merge
14h 32m
Merged PRs (30d)
19

Description

## Description

Taking the vanilla v3 playground https://codesandbox.io/s/docsearchjs-v3-playground-z9oxj as an example, there's a few accessibility-related oddities and issues that should be corrected. There's likely more, but a few things that caught my eye right away:

### Incorrect role/attributes on dialog

Once the search dialog appears, the container for the search currently has `role="button" aria-expanded="true" aria-haspopup="listbox"` and is made focusable using `tabindex="0"`.

The container should instead have `role="dialog" aria-modal="true"`. It can't be a "button" because buttons can't then have focusable controls inside them.

While focus has been made to cycle/remain inside the dialog, it's still possible for a keyboard user to jump back out and into the underlying page (navigating/setting focus through the page behind the semi-transparent overlay) - for instance, using `Alt+d` to set focus to the browser's address bar and then `Tab`bing forward.

![Screenshot showing focus on the 'Search' control behind the semi-transparent overlay of the example dialog](https://user-images.githubusercontent.com/895831/164895121-89c8c048-b6af-42f9-9aa2-cb781e3326db.png)

Likewise, the underlying page is still exposed to assistive technologies (i.e. screen readers). Using `aria-modal="true"` most modern ATs will ignore anything outside of the dialog, but for older browser/AT combinations, you'd probably want to use `aria-hidden="true"` on the underlying page (for this to work properly though, the modal container itself must live outside of the element that you've set to `aria-hidden="true"`, otherwise it will be hidden as well - and `aria-hidden` can't be overridden in a child element by using `aria-hidden="false"` either).

Video using Chrome/NVDA on Windows: after opening the dialog, exit form entry mode (`NVDA + Space`) then use reading keys (cursor keys) to navigate right back out of the dialog and into the underlying page, as it's still exposed to AT.

https://user-images.githubusercontent.com/895831/164896236-ea2780b2-a1d0-4543-ac76-6f90fbbbf0f7.mp4

One way to work around this would be to either use the new `` element (which takes care of most of these), or to use the `inert` attribute and relevant polyfill https://github.com/WICG/inert

### Incorrect role/attributes on the search input itself

The input in the dialog itself should have a `role="combobox"`, `aria-expanded="..."` (true/false depending on whether or not results are shown) and `aria-autocomplete="list"`. See the [Editable Combobox With List Autocomplete Example](https://w3c.github.io/aria-practices/examples/combobox/combobox-autocomplete-list.html) from the [WAI-ARIA Practices 1.2 combobox pattern](https://w3c.github.io/aria-practices/#combobox).

### Focus lost/not managed when closing dialog

When the dialog is closed, focus is currently simply lost (`document.activeElement` goes to `body`). While browsers often try to compensate for this, it's not reliable. The end result is that once the dialog is closed, users are bounced right back to the very start of the document.

Video using Chrome/JAWS on Windows. Note how once dialog is closed, JAWS' reading position is essentially the start of the page again (the heading before the search button).

https://user-images.githubusercontent.com/895831/164896357-8460d20c-4408-4965-a1ae-31f0f210cddb.mp4

This can be particularly problematic if there's a lot of content preceding the search button, as the user will have to navigate through all that again before reaching the position they were at when they triggered the dialog.

Ideally, once the dialog is closed, focus should be moved explicitly back to the search button that triggered the dialog in the first place.

### Low contrast text

Assuming these are the default colours that come with this dialog out of the box, they have exceedingly low contrast

![Screenshot of the low contrast grey on white/grey on grey text in the dialog](https://user-images.githubusercontent.com/895831/164895437-967a5b0f-fdb9-4bd8-b865-f6dfb4ad3e9a.png)

"No recent searches": grey (`--docsearch-muted-color` / `#969FAF`) on off-white/light grey (`--docsearch-modal-background` / `#f5f6f7`) has a contrast ratio of 2.5:1

The various keyboard hints an "Search by": grey (`--docsearch-muted-color` / `#969FAF`) on white (`--docsearch-footer-background` / `#fff`) has a contrast ratio of 2.7:1

These all fall below the recommended 4.5:1 minimum threshold from [WCAG 2.1 1.4.3 Contrast (Minimum)](https://www.w3.org/TR/WCAG21/#contrast-minimum)

Likewise the keyboard shortcut SVGs have exceedingly low contrast, which fails [WCAG 2.1 1.4.3 Contrast (Minimum)](https://www.w3.org/TR/WCAG21/#contrast-minimum) for the text-based ones ("Esc", and "Ctrl/K" in the initial search dialog trigger), and [WCAG 2.1 1.4.11 Non-text Contrast](https://www.w3.org/TR/WCAG21/#non-text-contrast) (3:1 minimum threshold) for the arrow/enter key ones.

Contributor guide

Open the contributing guide

Research direction

Start with the vanilla v3 playground linked in the issue and inspect the search dialog, its input, trigger, focus handling, and default color variables. Compare the dialog and combobox behavior with the cited WAI-ARIA patterns and WCAG contrast requirements. Done means the dialog is correctly exposed, focus is contained and restored, the input has the required states, and the default text and key controls meet the stated contrast thresholds.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
accessibility, frontend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
38/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.