Building animations in React Native with accessibility in mind

Marton Bodonyi
Brain Waves
Published in
4 min readJan 31, 2022

--

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!

--

--

Marton Bodonyi
Brain Waves

Senior Software Engineer at Seer Medical, Technical co-founder of Anycamp, and teacher at Lewagon