Video details

React Native EU 2021: Sanket Sahu - Building Accessibility Hooks for React Native & Web

React Native

This talk was presented during the React Native EU 2021 - the largest community conference in the world focused exclusively on React Native.
Abstract: Accessibility shouldn't be a choice that developers should make. It should go without asking. Syncing states, adding the support of screen readers and keyboard interactions can be cumbersome. My team and I have built a set of React hooks that make it easy to build accessible React Native and Web components that complies with the WAI-ARIA standards. It's an adoption of React Aria (by Adobe) in React Native for mobile platforms. The web support is also enabled using React Native Web to make universal components that are accessible by default on all the platforms. We call it React Native Aria. Let's talk about it!
About the speaker: Sanket is the founder of GeekyAnts - a Design and Development studio which is the team behind popular Open Source projects such as NativeBase, BuilderX, SyncState and other. He is on a mission to empower everyone to build things and has spoken at conferences such as ReactNative EU, React Europe, ReactDay Bangalore and others. Fun fact - he is also amazing at playing the guitar and has a studio at home!
Twitter: GitHub:
Additional links: Slides:


This conference is brought to you by Code Stack, React and React Native development experts. Hey, everyone, I'm Super excited to be back at React Native you. And today I'm going to talk about building accessibility hooks for React Native and Web. I'm Sunkeyte. I'm a software engineer at Geekyans, and yeah, I go by the way. Handle Sunkit Sahoo. You might have come across this tweet, which went viral. I'm tuning in from the beautiful city of Bangalore. I wish I was there, and I wish it was an in person conference, but yeah, here we are. This nice illustration by Abby Buck so thank you so much for that. So let's get back to the topic and try to decode that building accessibility hooks for React Native and Web. First of all, what is accessibility? I went to the Mdn docs and found this which broadly defines what accessibility means. So it is the practice of making your websites usable by as many people as possible. I think the same applies to apps too. So it would be websites and apps making them usable by more and more people. That's a very broad definition. So if we narrow it down into like, what are the characteristics or what are the support that you need to make your website accessible? It would be something like it should be compatible with screen readers so that people with visual impairment or low vision can use the screen readers and understand what the app is all about or what the website says. And the same thing applies with contrast ratio with people with low vision. And then we have responsive design like the app or the website needs to be accessible on Mobile's, smallest mobile out there and to the desktop and maybe to the largest display out there 108 inches, TV or something and keyboard accessible. I think this I really am fond of using keyboard slot and I use like, tabs and arrow keys a lot and websites that don't work with keyboards. It's really hard. So let's see, what are these things and how we can enable these things in our websites and apps. So how to build accessible websites. And I'm going to talk specifically in terms of React. So straight to the documentation. Documentation says that web accessibility also referred as eleven y. It can be enabled. We can work on this and React fully supports building accessible websites, often by using standard HTML techniques. So what are these standard HTML techniques? W three, C and WCAG. These are like guidelines. Wcgag is the guideline that is provided, and we can go through all the things that we can do. So it's usually with attributes that you can add to HTML markup and that makes the particular page or app accessible. Let's see an example. For example, if there is an input box and I would like that to make it are compatible and make it required for people who are using it with just say, screen readers so I can pass in a prop called Ariaphen required as true. And this is an HTML standard attribute that is also supported in React. If you pass that when we are using a page with this input box with a screen reader, it says that this is a required field, and we can also add a label something like Aria label and drop in some label and it reads that loud. So React and HTML standards for Aria is more or less the same thing. But React provides Reactivity on top of it, which makes more sense. So let's see that in detail. So how do we create a component? A component can be created by these five steps that I always come back to writing the markup, doing the styling and adding interactions like handling events and then handling the States and last but not the least accessibility. Let's take an example of creating a checkbox component for the web. So say I want a check box, so I'll wrap it in a label markup and then have input type checkbox and some text around it. As step two, I would add some styling just with class names. Here no CSS in JS. Next we can add interaction, for example, on the right side you can see as you click on the checkbox. It shows an alert message. So pretty standard stuff. Input on change alert and then it does the trick. Next, let's make it talk to the state and let the state update the Dom. How do we do it? So create state and then on change at that state and pass in the same value in the checked value of the input box. Check drop of the input box. As we do it, we click on that and then state is updated and the screen the component rerenders. Last accessibility. So we have props like Aria checked Aria hyphen labeled by that we are going to use here in this input box is the same value that we pass to checked prop input. We can use the same thing and pass it to Aria checked. So with screen readers or with when we use keyboard. So this says that the current value of checkbox is checked and the label also reads out we can have are you labeled by as? I agree. So one thing to note here is that is the Reacts component state that is building the initial UI and it's not just the visual UI that it is building. It is also building the accessibility tree structure and accessibility like something that is not that can't be seen by the users just by the screen readers. It also builds that and whenever that is being updated, it's updating the state and that reactively updates the area values as well. So React is working for both the things for the visual aspect of things and the non visual aspect of the things, which is super interesting. And here we are using standard input of type checkbox, so we don't have to do much. But we can also make use of say something like this and make it behave like a check box by adding something like role is equal to say checkbox. And then we have our checked in there and labeled by. Visually, we can style a Div like a checkbox. But to make the browser understand and the users of the browser understand that that particular Dev is a checkbox, we can use Role property. Great. Let's move on. So let's see accessibility for mobile for iOS and Android. And to do that, we'll use React native so straight to the documentation. React Native also provides unified API for iOS and Android to make the apps accessible. For example, we can say that a view which is equivalent to which is somewhat like to Div accessible is equal to true. So as we do that screen readers start identifying this piece of this block of code as accessible unit and it starts to read out like text one and text two at the same time. In this example, both the text notes are not accessible directly, but the view wrapper view is accessible and the screen reader reads Comcast everything inside that like text one text two and it reads that out. It also has focus management and things like that which we just maps by using this accessible is going to true. Anyway, we have more props that can be used. So we have things like accessibility flow and accessibility label and accessibility role and state and value these two very important. That makes the end users understand what type of element they are focusing on, and then what's the current state and what's the current value all these things. Apart from these three, there are really important ones and the black ones are supported on iOS, whereas the green ones are for Android. So let's create a checkbox component for mobile devices, so standard reactive. We'll use the pressable component. We'll create a nested view inside that and add some text, then add an icon and style it with standard reactive style sheet create and then add handle the state on press handle toggle update the state and also update the UI based on that state. Checked with checkbox marked and checkbox blank outline, and then we need to wire the same state with the accessibility role. So here we are using accessibility role as checkbox and accessibility state as checked. Now this makes it work for screen readers for the visual aspect of things, and it just works. So this is a very basic example of how accessibility can be enabled on top of the existing UI not checked checkbox. I agree. So this is a quick example of how screen readers work when we have accessibility enabled. How can we do the same thing for Web or can we write a unified Mark up or unified component that works on both the platforms? Yes, it's pretty much possible. We can use React native web to map the same reactive API on the web, and let's see how that can be done. So let's assume that this is our dream API and this is what we want to do. Like create a checkbox component that works on all the platforms. It takes an ischeck prop and it has on change handlers that updates the check value and then it has text inside it. That says, I agree. So to build this and to make it look the same on iOS, Android, on Android without losing the capabilities of the native accessibility on all these platforms. How can we do it? Let's see. So we can abstract out the UI part and create a component, say custom checkbox UI that's a dumb component takes in check and then gives us the checked UI of that we can pass in false for the check value and just empties out the checkbox. Great. And to make it accessible, we have to write some conditional code. Reactant Web handles it well, but there are cases that we'll have to write something specific for that. The first default thing that comes to our mind is handling the keyboard versus handling the touch events. So here's a quick example of how we can make the same checkbox UI accessible on different platforms, so we can write some conditionals with platform as well and then write if it is web, then use the native input and write the on change and type as checkbox. So this does most of the trick if we have input as checkbox, but on the parent if we see we have accessibility role as label and this makes it tapable on the web or maybe sorry, clickable on the web. And here we are using the same custom checkbox UI. And if you have a look at the input on change, that component is wrapped in a visually hidden view, so it hides the real input box and shows the custom checkbox UI while maintaining the accessibility aspect of things. Because the wrapper view at the top level has accessibility role as level. Great. And for mobile phones we go ahead and add accessibility role as checkbox accessibility state as checked. So on the Web, where exactly are we handling accessibility role as checkbox. So we are using a native input type is going to checkbox. So that does the trick. We don't have to specifically notify that we are using a checkbox and then update the state accordingly. So this piece of code works on all the platforms. Like for native React native does the trick on web. We are using a native input box input type box and then this works. So this is a very simple and a high level example of adding accessibility that works everywhere. There are more things to consider. The first one is definitely keyboard interaction. An example of this would be when we are building, say combo box or select boxes. We focus that using tabs. And then when we press space bar, it opens up and we can use the arrow keys up and down and then press enter to select that value. Then it closes the pop up. That's one example. And this is like one of the hardest examples when it comes to adding accessibility to a custom combo box. It also goes as a joke in the community in the design systems community anyway. And then screen readers. We have to make it compatible with the labels and all those things and contrast ratio. Even the visual aspect of things those with low vision. Can they read the text? Do we have enough contrast ratio in the foreground and the background color? We have more than this. These are like just a few points, and that's where the A Eleven Y project comes in. It's a very nice project. They have detailed down, like all the different aspects of accessibility. They also provide a checklist that any developer or team can go ahead and check if they are compliant with all those things. And yeah, they have the compliance in, like, three different levels. Aa and AAA is essential sort of accessibility that all the apps and websites must adhere to. This can be something like adding all text, adding captions, adding placeholders. And whatnot like these basic things that is like essential for any app or any website per se. Then we have AAA is a little stricter than a. It has all the checklist of A, but it has a few more things. For example, the contrast ratio of text versus background must be at least 4.5 to one. That's one thing. Then we also have subtitles for the videos and a few other things. And this is like required by multiple government and public body websites. Then we have AAA is a very strong level of compliance. This is like, for example, it has a contrast ratio of seven to one. And then if there is any video on the website that has to have a sign language support for people who can't hear. So yeah, these three levels are really important to understand and also to cross check with the website. Like if your app or website has fallen under like which category anyway, they also have a checklist the Eleven Y project, for example, for keyboard. They have these three things. Make sure there is a visible focus style for interactive elements that are navigated to by keyboard. Then we have like, when you press tab, does it maintain the same order as per the visual layout? Or does it like jump from the first one to the fourth one and then goes back to the second one and then a lot of things like this. It's in their checklist and they have a very nice write up around it. Same thing for mobile and touch. Do we have, like, horizontal scrolling? If we rotate the screen, does everything reorganize? Well, so go ahead and check out the eleven Y project. This brings me to Reactor. This is a brilliant project by the Adobe team. Reactoria provides a set of React hooks that anybody can use to build accessible UI primitives for their design system or for just their component library. You shout out to Devon, who is heading this project at Adobe, and they also have another project in the same set of projects. The parent group of project is called as React Spectrum, which has React re and React stately. React Stately is the state management piece of building these UI primitives. For example, we have used toggles state as a hook. Let's see that. Let's see one of the examples. So to build the same checkbox. If you're using Reactor, we can use toggle state from stately and we can use checkbox from Reactoria and then we can have a label and input and spread that input props that comes from use checkbox right into the input element. And yeah, this does all the trick of making that particular component accessible with keyboard with mouse on top of it and for screen readers and everything. Also, these hooks are like service layers, and it's more like they don't provide any UI. So the keyboard handling or mouse handling and the accessibility part of it. All these things are like abstracted out, which can be dropped into other UI components to make them accessible. And that's the beauty of Reactor. This is an example and we can go ahead and use checkbox and this just works. It also gets all those props like is indeterminate and all the things that the checkbox has. Great. So then there's another project. This is called React Native Area. This extends the support of Reactoria to mobile phones, and this project a huge shout out to Nishan. He has worked a lot on this project. He's like a sole developer, but there were people in the team who helped them out. So let's see React Native area and how Nishan and team they have built this React native area. So React Native area is a set of React hooks to build accessible UI primitives for React native and well, it's a very similar thing, but it works for React native, but with the help of React Native web, it works on all the platforms. So here's another example. Import use checkbox from React native area and then use toggle state from React stately and then spread this input drops, which has like on change on press and accessibility state. So depending on the platform it returns if we need on change or onpress works for React Native and unchanged works on the web. So let's see so we can use like visually hidden that's another component that hides that particular input box that comes from Reactoria and then the custom checkbox UI can be used. And we just spread that input props that's received from Use checkbox and pass it on input. And the same thing also goes on the principal component in React Native and yeah. So it handles most of the things for accessibility, right from, say tab like focus ring or handling the keyboard interaction and checkboxes. Again, it's a very simple example. It gets really complicated when we have like menu or combo box or radio buttons. Here is the source code, a very high level source code that this hook provides. It takes in all the props and state and also the input ref of the checkbox, and then it returns the input props that is actually spread on the pressable component. If you see it in the last slide pressable spreads input drops. So all these things are passed back to that particular element pressable and it adds accessibility role and accessibility state, which is picked up by Reactive pressable component and on the website. So React Native has a file for used checkbox web JS. So this straight away imports Reactoria's checkbox, use checkbox and then export the source code of React Aria's. Checkbox is something very similar to this, but instead of using React Native specific roles, we use like Aria Hyphen check than check. Great. So we have a lot more hooks that's available in React Native area. Another example is Use Focus ring. This adds the focus ring on components. So when using keyboard and pressing tabs, we get the focus ring of the keyboard, which is independent of where the mouse cursor is, so we can use it like use focus ring and then spread it right away on the visible component. Next we have used Hover. Use Hover is similar to Use focus ring, but this is straight away. Does the trick of spreading Hover props and all those things which makes it like hoverable. Great. Then we have used overlay position. This place is the overlay, something like a tooltip or a pop over. We can use overlay position and this takes in the target element and also the overlay element, the rest of them obviously. And then places that gives the props like top, left, bottom, right position of that of the placement. And it just really works really well. So we can use a trigger component and then click on the button and then it just places that so that's used overlay use overlay position. And then we have more hooks like Use combo box, use slider, use menu, use checkbox, use group, use radio and switch tool tips and pop over. Great. So this is a joint effort. I would say that Nishan and team have worked on something on the React native side and then mapped back to Reactoria for the React system. And yeah, we have put all these things in UI component library in the next version of Nativebased. So Nativebased essentially is mobile first accessible components for React Native and Web. This is based on the utility first principles and React Native area is used here with many components of Natives to make it accessible and also to make it work on all the platforms. Native based components works on iOS, Android and Web, and it also behaves natively like with tabs, with Hover and a lot of platform level things. Yeah. So the checkbox example that we had in the earlier slides is actually available in nativebase, and we can go ahead and use it. And here is another example that is to create a menu component. It's really hard to make menus accessible, like pressing enter space, opens up the menu and then using the cursor it goes, let's see that example how this is done so we can press enter and then type even like RM and all those things to filter out or Hover that particular menu. So let's see if I can enter and then down and then we can type R and then M and it takes us there. This is what we developers do most of the time, isn't it? And the same thing works for screen readers on different platforms. So this is an example of Android. Let's see that I hope you can hear it. Tap more options menu Button pop up window menu item Arial menu item Tahoma Disabled menu item Roboto Expo go no options menu, but great. So yeah, those were like, few of the examples from React native area being used in Native base, and this is the team. They have worked really hard on building React native area plus native base, and it's open source. Go ahead and try to use it all ears on the feedback. Yeah, the team is trying to build it compatible for all the platforms. It's a hard problem to solve, to be honest, but yeah, let's see how far we go. That's all from my side. There are a few projects that you would like to check from the same team. There's a state management library called Sync State. Then we have React pluggable a form library using MST Formatt, and then Builder X. That's a design tool that codes and API all from me. I am Sanketh and go ahead and let's connect on Twitter. My DMs are open. Yeah, that's all for now. Thank you so much. You're.