Creating web applications can be challenging. Creating accessible ones - even more so. However the real challenge lies in maintaining accessibility in your project since it requires knowledge and skills beyond those of traditional web development. To make this happen, one must choose the proper tools to keep the accessibility level high when code gets refactored, monitor the accessibility status and test it automatically during CI. To tackle these challenges, I’ll introduce a different approach that intertwines accessibility into the gut of the web application by creating an accessible React components library. I’ll discuss the principles, tools and techniques I use to test and maintain the accessibility level over time, and provide you with the initial recipe to drive the accessibility change in your organization.
My Accessibility Journey: the Quest for an Accessible Component Library
AI Generated Video Summary
The Talk discusses the speaker's journey in making applications accessible and the importance of preventing inaccessible code from being shipped. It explores the process of building and creating accessible components, emphasizing the use of appropriate HTML tags and conducting functional and accessibility testing. The Talk also highlights the benefits of automation in testing and fixing accessibility issues. Overall, it emphasizes the importance of accessibility and provides practical tips for incorporating it into software development.
1. My Accessibility Journey
The first time I had an accessibility test, it was a success on one end, but a complete failure on the other. We worked hard to make the application accessible, but every time we made changes, accessibility was left behind. The code was full of patches and hacks, not maintainable in the long run.
Hi. The first time I had an accessibility test a few years ago, it was a success on one end, but a complete failure on the other one. We had an application and we worked very hard to make it accessible, applying many patches and specific accessibility techniques and accessible code, but every time we had to change something in the code, for example, a rebranding effort, new colours or a new interaction, accessibility was just left behind because no one remembered to test it. For that, it was most of the time it was broken, a lot like this. I mean, the code worked functionality-wise but if you look under the hood, it was full of patches, full of hacks, not something we were very proud of. And it was not something that you can maintain for a long while.
2. My Accessibility Journey: Introduction
In my other project, we did things differently to make it accessible from the start and in a maintainable way. This talk is about my accessibility journey and the quest for an accessible component library. Accessibility is about inclusion and letting everyone use your application. We want to prevent inaccessible code from being shipped. We start by testing the accessibility flow-by-flow, such as the login, forgot password, sign up, sign out, purchase, and contact support flows.
So that's why in my other project, when we started a new accessibility project and in a different company, we did things in a different way. We wanted to make it accessible from the start and in a maintainable way. And if you are tackling the same problem today or you're trying to make your application accessible in a way that will last, this talk is for you.
So let me start. This talk is called my accessibility journey, the quest for an accessible component library, or as should the full name be, my accessibility journey, the quest for an accessible component library that reflects and redesigns and is maintainable and testable. Which are like small points, but they are very important for us to have accessible code.
So let me introduce myself. I'm Asaf. I'm the father of Sahr, Naziv, and I've been in the web development field for over a decade in various roles and currently I'm the frontend tech lead for Avinst, which is a startup that specializes in giving developers great developer tools for accessibility. For example, we have algorithms based on computer vision and machine learning that help to detect and find accessibility issues. We create Chrome extensions and other extensions for mobile as well that help developers and testers to find their issues on their applications. And we develop SDKs that expand testing frameworks such as Cypress or Selenium and give them accessibility add-ons for their testing. I'm going to dig into the last one in a short while in this presentation.
So before we start, what is accessibility? Accessibility is about inclusion. It's about letting everybody in. Letting all the people use your amazing application. For example, a person who has a physical disability and cannot use the mouse will still need a way to navigate through your website, and to click on your drop-down and to select the third option that opens another submenu, and then to select the fourth option from there. So if you have some kind of navigation or some kind of interaction for the users that we all have in our applications, you want to make sure that this is also accessible for someone who cannot use the mouse. And it's not trivial. It should be, but it's not. So what we do is we want to prevent these kind of things from leaving our code. We want to ship only code that is accessible from the start.
So when we want to make our own application accessible, we thought about where should we start doing this effort? So we had several ideas. It all came from the testing side of things. I mean, these ideas are very much like discussions we had about testing. So we can test the product or test the accessibility of the product flow-by-flow. For example, we can cover the login flow, start with the login screen, and then confirm that the login pop-up is valid, that the forgotmypassword flow works, and sign up and sign out also works with the keyboard and with screen reader, which is an accessible technology, for example. The same for purchase flow and the same for the contact support flow. Sorry for my voice. I have a bit of a cold.
3. Building Accessible Components
Another option is to go page by page and cover the entire accessibility aspect of the homepage. We can think about components and break down the application into small components. Then, we focus on building each component as accessible as possible using appropriate HTML text. Finally, we automate functional tests and accessibility tests.
Thank you for completing it in your head. So another option is to go page by page. If we go page by page, for example, let's cover the entire accessibility aspect of the homepage. Let's make sure that every image in the homepage has an alternative text. Every button can be accessible by keyboard. Every form has a label that a screen reader can tell the person who is looking at the website what the label is.
But there's a third way that comes more naturally for us as developers. This is by thinking about components because as modern front-end developers we tend to think about the world or about applications as built out of components. For example my website is built out of buttons, forms, popups, labels, input fields, maybe drop menus, select boxes, check boxes. We are doing composition, we are taking this component and that component and we assemble forms, or assemble graphs or assemble pages. Let's have a big table and a menu and some text field. And as a disability company we wanted to make sure that our own application is accessible and we decided to start from the component level. I mean, flows are a valid way. Assemble pages, but components we love. And this is the recipe that works for us when creating our own accessible component library.
So the first step is to break down the application into small components. In our case we had four applications and we needed to identify the common components and maybe change the API so it will be the same for all of them to match all of the use cases. And then we put them in a separate Git repository. But first it starts by identifying which components are in common for all the projects. Second, we focus on the components one by one and we try to build them as accessible as possible using the appropriate HTML text. I will dive into that in a minute. And third, we automate the hell out of it. We are automating functional tests and accessibility tests. Let's dive into it.
So the first part is to break it down into small components. Let's take this imaginary application for example. Imagine it's like a website. You can book a Harry Potter character, and it will come to you. It will come to your house, or to a place that you want, and will pay you a visit for a small fee. It's a great website.
4. Creating Accessible Components
Let's identify some components: dropdowns, date picker, and a search button. These components can have different states and appearances. We separate them into a common repository and focus on functional and accessibility tests. Our stack includes React, TypeScript, Storybook, Cypress, and CircusCI. Now, let's create an accessible button that can be focused using a keyboard.
If you find the real one, please let me know. I'll use it for sure for my daughter's birthday. So let's identify some of the components here. Here, I mean there is a dropdown that you can select the character. There is also a dropdown here that you can select the location, and there is a date picker. It is now marked in pink. You can select the date that the character will come. And there is a search button, which is a button. And this button, for example, can have an enabled state, a disabled state. It has a hover state. Like when you hover over it, or when you focus on it with a keyboard, maybe tells some kind of tooltip. Maybe the tooltip has a specific design or a specific appearance in specific cases. Same for the dropdown, and the same for the date picker. It can be a pretty complex component.
Now, after we identified these components, we are separating them from our repositories, from our product repositories, to a common repository, which its sole purpose is to be a designated repository for these components. In our case, we call it the Common Component Repository, not very unique, but pretty straightforward, which is good naming. And afterwards we consume this by all the products. And this component has different sized building blocks. It can have a small button or input field. It can have an entire table that has filters and has an ability to talk to the server or to work locally and to have sorting mechanism and to have some kind of error handling inside of it. I mean, it can be a pretty complex component as well. And because we went with this approach, we also decided to focus on functional and accessibility tests for these components. The stack that works for us and is also suitable for this conference is React and TypeScript for building the components. And we use Storybook to visualize the components and also as a basis for our tests, which I'll just show you in a little while. And we use Cypress for tests and CircusCI for continuous deployment.
Okay, so the second part, now we want to create an accessible component. So let's make an accessible button. Let's create an accessible button. What does it mean for a button to be accessible? Let's think about it. Well, some of the characteristics that make a button accessible is that if you cannot use a mouse like we said before, you should be able to focus on that button using your keyboard.
5. Creating Accessible Buttons
When creating accessible buttons, it's important to provide focus indication, support alternative key presses, and use the role attribute to inform screen readers. The HTML button tag provides these accessibility features for free, saving time and effort. This approach applies not only to buttons but also to other HTML tags like input fields, labels, and headings.
And after the button is in focus, imagine you have like five buttons in a row, you need to give an indication of which of the buttons is in focus. And then if you focus on it, you need to support the Enter key or Spacebar key as an alternative for Click. And the last thing, we want to hint assistive technology that the element is a button. So it will, no, it will tell screen readers or other assistive tools that this is a button.
Okay, now when we have these demands in mind, let's go into the code. So this is a basic start for a button. It's a Div, it has some class and ID, so we can use it for styling. It has an OnClick that opens an alert, and it says, I'm a button. Now let's make it focusable with keyboard. To do it, we'll use the TabIndex attribute. The TabIndex attribute tells the browser that this element is on the tabbing list. So when the user clicks the Tab key, he will or she will eventually focus on this element. Now we want to make sure that the Enter key works. So there is not really an easy way to do it, but to add an event listener that listens to key press. And now we need to filter these key presses to see, okay, so if it's an Enter, we need to trigger the function. If it's not enter, we should do nothing. Maybe if it's a space bar, we should also trigger it, depends on the operating system, I'm not sure. But some things need to be done there as well. And now we want to tell screen readers that this element is a button, so we will use the role attribute.
Okay, so what we have here is a working button, but it's merely the start of a button because our button will need to have enabled state, disabled state, primary mode, secondary mode, maybe a mode for a button with images, maybe it should have like specific state for a specific page. I mean, the code will only increase from here. And this code actually doesn't even cover all the accessibility aspects. It needs a lot of code. What if I tell you there is a different way, an easy one? What if we will just use HTML button tag? So, what will happen if we use the HTML button tag? We will get all of these things for free because HTML has some great accessibility features baked inside of it. So we will get keyboard focus, with some indication. You can style it if you want. We will get the on key press, and we get the row for free, and we don't need to worry about it. So, the first thing we learned from building our own Accessibility Component Library is that we need to love HTML tags and not just row divs for everything. It will save us lots of time in testing, and we just give us features for free. This is true for buttons, but it's also true for input fields, for labels, for headings, for other attributes.
6. Adding Automation and Accessibility Testing
To add accessibility component testing, we create a button component using the button tag. We use Storybook to create primary and secondary stories for the button. We isolate the component in a separate tab for functional and accessibility testing. Using Cypress, we visit the URL, click the button, and assert the click is registered. We expect an accessibility framework to find missing alternative text, unfocusable buttons, inaccessible pop-ups, and insufficient color contrast. In Events, we use our own tools and an SDK for Cypress to gather accessibility issues and run validations.
Okay, and let's talk about adding a level of automation. So, to add the accessibility component testing, automated testing, first let's create a component. So, this is a component, it's a button. We learned from the previous slide that the button has to have the button tag. So, we use the button tag. It has, the thing that interests in here is the primary prop, which said that, is it a primary or secondary button? Now, we select this button and we create two storybooks stories, the primary story and the secondary story. If you're not familiar with storybook, it doesn't really matter. It's a great tool, but it's not the subject of this talk. But go try it, it's really great.
So if you run storybook, we'll get, actually we get two screens that render only the buttons, and it looks like this. It has the primary button, it looks like this, and the secondary button that looks like that. A bit different colors. Now, we will use this as a basis for our tests. In storybook, there is a magic button, I put a bunch of arrows so we won't miss it. If you click it, it opens the component in a separate tab, actually without all the wrapping of storybook UI. So, it will open without the toolbars, and it will isolate only the component we want in a specific state with specific props. We will use that as a base for our functional and accessibility testing.
So, this is our functional test. We will use Cypress for it, and the test is pretty simple. We see two tests which are identical, first for primary button, and second for the secondary button. They visit the URL that storybook created. We click on the button, and we assert that the click is registered. And if we wanna run it with Cypress, we see that everything works, and it's great, it's green again. Okay, now let's add accessibility to the mix. So, what should we expect from an accessibility framework to find? Some of the things that we wanted to tell us is that there is a missing alternative text on an image, or we have a button, but it's not focusable by keyboard, or we have a pop-up, but the pop-up is not accessible, or we have text in some color and with some background color, but the color contrast is insufficient, so it's hard to see for people with low visibility. All of the things and more are the things that we are working on in Events. These are kind of the things that we are detecting using our engines. So, because we work in Events, we want to use our own tools, so we use our own tools also for test automation. And we do it by providing an SDK for Cypress that gives us the ability to gather accessibility issues. So, if we call evstart, this is the command, it says, Events, please start gathering accessibility issues and then we do some things and we call evstop and then it gathers all of these issues and we can run our validations against these issues, run the expect or assertions in our test.
7. Running Functional Tests and Fixing Issues
So this is how it looks. We run the functional test, check for accessibility issues, and fix any bugs. We replace the color contrast issue with black. This process happens in our pipeline. Our component library consists of more than 40 components, used across four projects. The library and our approach saved us during a rebranding effort. Takeaways: divide and conquer, be friends with HTML, and automate as much as you can.
So this is how it looks. The middle part of the test, you can identify it from before. This is the same test, the functional test. Now, before we run the functional test, we call evstart, so it will start getting accessibility issues and after the click is done, we expect that there are no accessibility issues at all. So let's give it a try.
Okay, now we run it and we see that things are not going very well. I mean, there is a bug. So, let's look at the report and we see that there is a color contrast issue and the image hints that it's related and the selector that it's related to the contrast between the text color and the background color. To be more specific, there is a contradiction, a bad contrast between RGB 104, 100, 100, 06, 09 and white. Well, because I'm not a qualified designer, sorry, I do what any good developer would do and we say let's replace it with black and it works. Now the color contrast is great. In real life, I would consult a designer but this is a talk and I'm alone here.
And now this is for a single component and we do this for all of our components and this process happens during our pipeline. So every time we push new code, we start Storybook, we run all accessibility tests and our functional tests and if everything goes well, we deploy a new version of the component library to be consumed in other products. So this is how it looks in real life. Sorry. So our component library consists of more than 40 components, more than 170 stories and tests. Each story is covered with both functional and accessibility tests. It's used across four projects. We are a team of six people, almost seven people. Depends how you count. And this library and this approach saved us, saved our accessibility doing a huge rebranding effort we just did. So we changed. Basically, both of the components were changed, but the accessibility level was kept high because we have the test harness to keep us accessible at all times.
So before we end, takeaways. If you want to do the same or if you want to take advantage of the same approach, first, divide and conquer. Split your code into small components. Be friends with HTML, get to know your HTML tags and automate as much as you can. Automate accessibility, automate your deployment pipeline. It will save you lots of time.
8. Concluding Thoughts on Accessibility
Accessibility is not taught in academia or bootcamps, but it's important. Don't overthink it, start with one component at a time. Thank you for listening, it was fun talking at the conference. I'll be available for Q&A and feel free to contact me on LinkedIn or my blog. Accessibility is more accessible than you think.
So to sum it up, accessibility is not something taught in the academy or in bootcamps. And it's a shame because it makes developers feel inconvenient with it at first, but it's so important. So my advice to you is don't overthink it. You don't have to, must have a PhD in accessibility to start your accessibility effort. You can take it one component at a time. Just start.
So I want to thank you for listening. It was a great fun talking here in the conference. I will be available in the Q&A session in a short while and feel free to contact me on LinkedIn or via my blog. And if you hesitate, just remember that accessibility is much more accessible than you think.
Thank you very much.