5 things I'm thinking about when I check a Pull Request for accessibility
Tags: a11y, webdev, javascript
Published: 2021-03-30 11:24:05

_(Photo by [Cookie the Pom](https://unsplash.com/@cookiethepom?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/laptop?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText))_
  

Developing reliable, accessible, apps is really a whole-team effort, and something I've not written much about before is how I approach things when I'm _not_ the one writing the code. 

This is by no means a complete guide to implementing or testing for accessibility, but hopefully it gives a general idea of things to think about when reviewing a Pull Request 🙂 Feel free to leave any of your own tips, suggestions, or questions in the comments!

**If you'd like to skip directly to a section:**
1. [What even is this feature?](#1-what-even-is-this-feature)
2. [Initial check with axe](#2-initial-check-with-axe)
3. [Keyboard operability](#3-keyboard-operability)
4. [Screen reader checks] (#4-screen-reader-checks)
5. [Considerations on focus management and dynamically appearing content](#5-considerations-on-focus-management-and-dynamically-appearing-content)


## 1. What even is this feature? 🤔

I find it's quite useful to take a step back and consider what UI pattern we're trying to introduce/refactor, and check the [WAI ARIA Authoring Practices](https://www.w3.org/TR/wai-aria-practices-1.2/) for a reminder of how that kind of UI pattern _should_ behave. 

Those docs are great to bookmark for development too, as they lay out expected behaviours, aria attributes, and link to example implementations. 

Stepping back and asking yourself "what is this thing?" also helps spot opportunities to replace `div`s with more semantic alternatives. I've lost count of the amount of times I've had a lightbulb moment of "oh wait, this is actually a [insert something that should be obvious here]!". 

## 2. Initial check with axe 🪓

The [axe browser extension](https://chrome.google.com/webstore/detail/axe-devtools-web-accessib/lhdoppojpmngadmnindnejefpokejbdd) helps us capture a lot of low hanging fruit, e.g. colour contrast, missing landmarks or labels.

If there's multiple states the feature can be in, I'd try re-running axe **in each state** (e.g. a dropdown that's collapsed, vs expanded), as axe can only inspect the current DOM.

## 3. Keyboard operability 👩🏻‍💻

**NB: If you use a Mac and/or Safari, please make sure your settings allow for tabbing to interactive elements.** See [Browser Keyboard Navigation in macOS](https://www.a11yproject.com/posts/2017-12-29-macos-browser-keyboard-navigation/)

All features should be operable by keyboard alone, and this includes:

- Pressing `Tab` to move through each of the interactive elements in a logical order (e.g. often this would be top-to-bottom, left-to-right)
- Pressing `Shift + Tab` to move backwards through those elements
- The currently focused element should be clearly visible (e.g. with a focus outline). 
- You should be able to interact with focusable elements as per the conventions in the [WAI ARIA Authoring Practices](https://www.w3.org/TR/wai-aria-practices-1.2/). For example, activating a link with `Enter`, moving through combobox suggestions with `Up Arrow/Down Arrow`.
- Being able to disclose content that would otherwise be triggered on a mouse hover (e.g. a tooltip that makes helper text appear on hover)

### Bonus tip: invisible focus problems

If you ever get stuck debugging invisible focus issues, you can add this in the console to log out the focused element as it changes: 

```js
document.addEventListener('focusin', () => console.log(document.activeElement))
``` 

## 4. Screen reader checks 🤖

I've been asked a few times "Do you always check with a screen reader?" and the honest answer is "No".

My personal view is that a screen reader check is a **must** when:

- We are introducing a new interactive feature (as opposed to a content change): things dynamically update/appear/disappear
- Any `aria` attribute has been changed or introduced: these are only surfaced through assistive technology, so if we're not checking with a screen reader, we're not really checking at all

### A little bit of initial setup

I usually use VoiceOver and Safari to conduct screen reader checks. This is mostly because VoiceOver is the default Mac screen reader, and is designed to work best with Safari (if you try using it with another browser you'll notice some buggy/unusual things).

If you use a Mac, I have a post with some initial setup instructions: 

{% link https://dev.to/s_aitchison/3-quick-tasks-to-get-familiar-with-screen-readers-voiceover-on-mac-1cig %}

If you don't use a Mac, I would recommend using [NVDA](https://www.nvaccess.org/) and Firefox/Chrome, purely because NVDA is a free download and is very widely used (check out the latest [Screen reader user survey](https://webaim.org/projects/screenreadersurvey8/).

### Toggling VoiceOver on/off

If you have a keyboard with the function keys in the top row, you can turn VoiceOver on and off with `Cmd + F5`. 

If you don't have the function keys, you can press the TouchID button three times in quick succession to bring up the accessibility options, where you can check/uncheck 'Enable VoiceOver'.

### The rotor

I usually start a screen reader check using the VoiceOver Rotor (opened with the key combination `ctrl + option + u`)- it's an interactive menu that lists different elements by type (e.g. landmarks, links, form controls):

![Screenshot of DEV home screen with VoiceOver rotor open. A list of links is visible](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jflz09zciszcll5j9qb3.png)
 
Press the left/right arrow keys to move through the different menus and get a quick overview of the relevant landmarks and accessible names of elements on the page. In the example above, you can quickly spot the 'Home' link has accidentally been named twice!

To jump to a particular element/section, use the up/down arrows to highlight and `Enter` to select.

You don't have to use the rotor at all if you don't find it useful, I just prefer it compared to reading through lots of the page to get to the section I'm interested in.

### Accessible names

Axe will usually help flag this kind of issue, but as I navigate a feature with a screen reader, I tend to be on the lookout for elements where:

- There is no accessible name (e.g. we've used an icon button with no aria label)
- The accessible name is vague (e.g. 'click here' - to do what?)
- The accessible name is repeated (e.g. lots of "toggle dropdown" - which dropdown?)

### Bonus tip: silencing VoiceOver

It can sometimes be a bit much hearing _everything_ announced as you're navigating around, especially if you're debugging one particular section. You can silence any in-progress VoiceOver announcement by tapping the `ctrl` key 🙂


## 5. Considerations on focus management and dynamically appearing content ✨

I usually pay particular attention to any features which involve content dynamically appearing/disappearing - for example: a dropdown menu, a warning banner, a modal. 

The main things I'd be thinking about for these is:

1. How does a low-vision user know that content has appeared/disappeared? Is anything announced via the screen reader?
2. If the new content contains any focusable element (e.g. a link) - how do I reach it? If I have to press `Tab` 20 times something's probably not right. 
3. If my keyboard focus was inside some content that's now disappeared - where is the focus now? 

Usually some `aria` attributes or manual focus management with Javascript is required to make these kinds of components accessible. Again, you can usually find what's needed in the [WAI ARIA Authoring Practices](https://www.w3.org/TR/wai-aria-practices-1.2/).