Empowering Users: Developing Accessible Mobile Apps using React Native

June 26, 2023

This blog post will explore and share some of the robust technical accessibility strategies and best practices we implemented for a mobile voting application using React Native.

Specifically, we’ll look at Formidable’s open-source library react-native-ama which allowed us to construct a component library that served as accessible UI primitives. This approach let us focus on what we do best—building great applications—while simultaneously ensuring that we prioritize accessibility, baking it into each component by default. Then, it will mention a few other handy components and hooks we used, and hopefully save yourself a gotcha or two.

In many ways, building an accessible React Native mobile application is easier than ever before thanks to both React Native’s internal efforts as well as the community’s. With react-native-ama it's not about adding accessibility features as an afterthought, but integrating them into the core process of your app development. As the react-native-ama library puts it, it's about making "Accessibility a First-Class Citizen". (For more on this, check out this insightful blog post).

A diagram of building accessible component primitives using React Native AMA and Restyle - drawn with Excalidraw.

Component Libraries with react-native-ama and Restyle

One of the best parts of react-native-ama is that it provides a suite of component primitives with built-in best practices for accessibility. In essence, you get these accessibility features for free, just by using these components. Moreover, AMA has a range of runtime checks in development mode that automatically log violations and warnings, and even apply stylings to these violations, so it’s easy to see when and where you may have missed something.

Another standout feature of react-native-ama is its "headless" architecture. This means you can use any component from the library while maintaining complete control over its styling and design. In our application, we used Shopify’s open-source restyle theming library to handle the theming and styling of our components, all resulting in a standardized and accessible component library, fully equipped with dark mode, breakpoints, variants, and more. Together, this groundwork let us build features fast and efficiently.

Case Study: Touchable Elements

Let's consider a practical example. Our application has a variety of buttons and touchable elements, including large and small call-to-action buttons, multiple choice selection buttons, toggle buttons, external links, and more. To create these elements, we began with the Pressable component from react-native-ama, and then wrapped it in Restyle's createRestyleComponent. This approach resulted in a completely themeable and accessibility-ready primitive component that we could then use to create more complex components.

Using this base button as a blueprint, we created our TouchableOpacity and TouchableHighlight components. These components were then wrapped to create call-to-action buttons, checkboxes, select boxes, and external links, as specified in the designs. This component abstraction allowed us to apply specific accessibility attributes that were relevant to each component. For example, we used accessibilityRole="checkbox" and the accompanying state role checked={true/false} for checkboxes, and accessibilityRole=“link” for external links. By doing so, we ensured that we had components optimized for accessibility whenever we needed any sort of Pressable inputs for any feature.

Rinse and Repeat

It's important to note that this strategy doesn't just apply to buttons and touchable elements. You can use this approach for any of the base components that AMA supports, including Text, TextInputs, Lists, and even the concept of Forms. Assembling a set of accessible primitives into your component library means that you can just build, knowing that you have at least a baseline of accessibility built in. You won't have to go back and "add it later.”

However, there may be cases where using components exported from react-native-ama does not work in certain situations, (perhaps you need to use components exported from react-native-gesture-handler, such as their Touchable).Fortunately, react-native-ama's documentation provides detailed guidlines explaining which accessibility features are included so that you can theoretically recreate these properties on a different base component. Additionally, you can always review the source code to see how it works. I think it’s important to reiterate that using react-native-ama doesn’t lock you in, you can use it as much or as little as is useful to you, and leverage it where needed.

Much like the button primitives we covered above, we also created a screen header component that included an autofocusing Text component. React-native-ama's Text autofocus prop comes builtin into the component, and this component announces the new screen's title immediately during screen transitions when using VoiceOver/TalkBack. Without it, React-navigation tended to up end focussing on the back button when changing screens, so this was a nice touch of polish. Similarly, we implemented a React context that provided values on whether the user prefers reduced motion or not. This allows us to adjust animations and screen transitions accordingly.

When using a third-party bottom-sheet library, I found that it didn’t prevent users from navigating outside/beneath it’s content when in VoiceOver/TalkBack. To ensure that VoiceOver/TalkBack remained within the presented content and didn't navigate outside that content, we used a custom context and a Screen component primitive that wrapped every screen. This made use of props such as accessibilityViewIsModal, importantForAccessibility, and accessibilityElementsHidden when the bottom sheet was open so that VoiceOver/TalkBack properly stayed within the present content.

In these cases above, we were able to work with react-native-ama and not against it to solve our specific use cases.

On Device Testing and Verification

It’s important to note that despite react-native-ama offering excellent development runtime checks and a built-in a11y-inspector for macOS, it's crucial to test accessibility on real devices using VoiceOver on iOS or TalkBack on Android. Luckily, you can also learn all about that in this iOS VoiceOver Guide for Developers blog post! It’s important and worth it to learn and test any new features in a variety of circumstances. Much like how a feature isn’t complete in React Native until you’ve tested it with both iOS and Android, I’d argue a feature also isn’t complete unless you’ve tested it with dark mode, larger text settings, smaller text settings, and using VoiceOver/TalkBack!

Wrap up

While this blog post focused on one aspect of mobile application accessibility, the topic is wide and full of possibilities. I highly recommend checking out the official React Native accessibility documentation to learn more about what's possible in React Native out of the box. While design has not been discussed in this post, it plays an essential role in creating accessible applications; keep an eye out for a future blog post on this topic. And finally, even though every application will have different requirements, I hope this post demonstrates the solid foundation you can establish using react-native-ama and the potential that lies in building from there.

Related Posts

Gradual Rollout for Mobile App Releases

August 29, 2022
Rolling out your app releases gradually will help you catch critical errors early and release with much more confidence. This is a guide for releasing apps with gradual rollout on iOS and Android.

Building Teams and Profiling Third Parties

April 21, 2022
Welcome to Part 2 of our series where we deep dive into the findings from our recently published report, ‘The State of Digital Transformation'.

Digital Transformation - Driving Success

March 9, 2022
As we enter 2022, the pace of digital change is at an all-time high and shows no evidence of slowing down. To address these changes and adapt to a swiftly evolving digital marketplace, companies are rapidly digitizing their internal operations, supply-chain management, and customer interactions.