Brain Waves
Published in

Brain Waves

Building animations in React Native with accessibility in mind

The Seer Mobile app helps people with epilepsy manage their seizures, track medications and have better conversations with their doctor.

Something that often gets overlooked when developing animations in apps is accessibility. I get it. You start by going down the rabbit hole of building complex animations (fun!), combining those animations with gestures (less fun), then trying to link that to react-navigation (“when will this end?”) and you’ve got yourself a pretty terrifying looking PR. Don’t get me started on unit tests.

Pull request toolbar showing 22 changed files
What have I done?

In all that chaos of building complex animations, it’s easy to forget to implement accessibility handlers to ensure people with Reduce Motion’ switched on receive a different experience. Reduce Motion doesn’t mean cut all animations. If you look at the way it’s implemented across the iOS and Android system stock apps, subtle animations like fades are all still maintained, but scale and transform animations get cut.

On the left, default motion settings on iOS. On the right, ‘Reduce Motion’ enabled.

Why it’s important

Let’s get something straight, I love animations. If there was an option in settings called ‘Increase Motion’ I’d probably tick that but as much as animations bring joy and magic to user interfaces for many users — they can do the exact opposite for some. Around 3% of people with epilepsy can have seizures triggered by flashing lights and visual patterns, but users can opt to Reduce Motion for other reasons too.

Enabling on device

Thankfully, unlike voiceover, you can enable reduce motion from within iOS simulator and Android emulators.

On iOS

On iOS it’s pretty easy to enable reduce motion. Jump into the accessibility menu, tap ‘Motion’ and check ‘Reduce Motion’.

On iOS: Settings -> Accessibility -> Motion -> Reduce Motion

On Android, frustratingly the ‘Remove animations’ accessibility option in Settings doesn’t get picked up by React Native. I haven’t been able to find much documentation on how to access that using Android native code but I did find this gem in the React Native documentation.

So basically, on Android it’s a developer setting. And to access it these are the steps you (or a user) would need to take…

There’s an open issue talking about this over at https://github.com/facebook/react-native/issues/31221, if you know of a way to implement reacting to ‘Remove animations’ in native Java code I’d be happy to help patch React Native to get it in there.

Detecting ‘Reduce Motion’ using a hook

In React Native, ‘AccessibilityInfo’ has an event listener and async method for querying reduce motion which can be neatly bundled into a hook to use in animations.

You can also use https://github.com/infiniteluke/react-reduce-motion but for simple hooks like this I think it’s better to maintain the code yourself, especially if you’re using TypeScript.

Wiring it up to an animation

The easiest way to reduce the motion of an animation you’ve implemented is to find which styles have translates in them and swap them out for opacity transitions. It’s neat and can hook in with gestures pretty easily but it comes with the limitation of needing to use a constant animation duration across all your animated styles.

Here’s some example code that implements the hook we created above.

Here’s what it looks like side by side in the simulator.

On the left, the popup scales using the default motion settings. On the right, the popup fades with Reduce Motion enabled.

Support in open source libraries

Reduce Motion support in popular React Native libraries like react-navigation is spotty at the moment so while you’re implementing it in your own projects, there’s an awesome opportunity to get some high-profile open-source PR’s in and make React Native more accessible in the process.

You can check out the useReduceMotion hook at https://gist.github.com/martsie/4f3bf6e3c67cf032ba562745a9c161af and example implementation at https://gist.github.com/martsie/a09b8192fe9ad40afc1a26ffc1c3c81c.

If you’re interested in working on delightful, accessible apps built in modern tech that genuinely improves the lives of people with epilepsy, come work with us at Seer!

--

--

--

Seer makes epilepsy diagnostics and management easy by combining medical expertise with the latest technology to improve healthcare for everyone. Here our engineers and designers share technical insights.

Recommended from Medium

Learn API by Building 3 Cool Projects— Part 1

How to use React and Tone.js to make a simple web audio application

Modular Synth

Having fun with ESDoc plugins

Vue3 Rookie mistakes

Deno: Request with Headers

Asynchronous Promises with JavaScript

7 Tools to Choose the Right NPM Package

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Marton Bodonyi

Marton Bodonyi

React-native mobile developer at Seer Medical, Technical co-founder of Aircamp, and teacher at Lewagon

More from Medium

Tracking Users Interactions With MixPanel using Javascript (React Native)

How to Solve React Native (IOS) Build Failed on Apple M1 Pro CHIP With Existing Application

React Native e2e testing with DETOX for newbies.

Using NativeBase v3 the right way