For the last couple of months, I’ve been working on refactoring a core piece of The transfer window for Pro users. Currently the Pro features are a bit hidden, and with a new design we wanted to highlight all the extra functionality you get as a paying customer (password protected passwords, extended transfer expiry dates etc.). Changing the transfer window was a big deal, because it’s a core piece of functionality and has been largely untouched for years! This resulted in a quit complex component and I decided to do a complete rewrite (in TypeScript), and start from scratch with accessibility in mind.

The component might seem like it has a lot going on, but when you break it down, it’s pretty simple. We have a container component (TransferWindowPro) that manages most of the state and is connected with Redux, switches between the expanded and collapsed UI. The expanded UI is used during the configuration of the transfer, and the collapsed UI is used to display different uploading states. When the window expands we transform the scale of the SVG to animate the layout of the file list, and it appears as if the configuration component slides out of the files list. All these transitions are triggered as components are added and removed from the DOM, with the use of a prop and react-transition-group.

accessibility improvements

From the beginning we wanted everything to be fully keyboard accessible and have clear focus states which sometimes wasn’t optimal from a design point of view (e.g. chrome doesn’t remove the outline after a click, the standard outline doesn’t adhere to rounded borders). So to solve these issues we decided to use :focus-visible to provide a different focus indicator based on the user’s input modality (mouse vs. keyboard). Because we need to support IE11 we also had to add the polyfill and a postCSS plugin so we can start using it today. For the rounded outline Josh Cameau had a great tip:

While I was writing these components, I wrote my unit tests with react-testing-library, which helps you to write your components in an accessible way:

One of the guiding principles of the Testing Library APIs is that they should enable you to test your app the way your users use it, including through accessibility interfaces like screen readers.

So while I was testing my code I used *ByRole selectors a lot, and found multiple accessibility improvements while I was developing and when I first went through the new transfer window VoiceOver over enabled, the text gave an ok representation what was on the screen.

In the transfer window we Reach UI (an accessible foundation for React components) where we can, and this helps making something like an accessibility complex component like a combobox, very easy. It was really cool to hear the VoiceOver highlighting that there are multiple items in the list.

I did run into some issues with the switch component I made, where the screenreader did not read out the label when you focussed. And when I came across the aria switch role, I rewrote that a bit and was able to describe the switches correctly.

my tips: <Callout list={[ write tests with react-testing-libary and follow their tips for good accessibility., use something like reach-ui for more complex accessibility patterns, Use VoiceOver for mac to check your component., use focus-outline and box-shadow for nice focus states. ]} />

the results