Accessibility at Scale

Alex Chudesnov
Wrike TechClub
Published in
13 min readMay 13, 2022
Illustration: a silhouette of a person with their arms wide open in a circle (one of the symbols of digital accessibility) which is wrapped aroung a DNA helix

At first glance, accessibility seems simple. After all, what could be easier than using buttons instead of divs? But when you start building at scale, everything gets a little more complicated. In this article, I’ll guide you through creating an accessible single-page app. I’ll start with basic components like a text input or popup and then explain how to scale them up to a platform that can handle hundreds of app views written by dozens of different teams.

What do I mean by scale?

Wrike is a versatile work management solution. The product is large, and our customer base is pretty large too, with more than 21,000 companies using Wrike.

Many people from different departments use Wrike every day to get their work done. They may have different workflows and processes and use different tools.

For example, program managers use resource planning tools, while designers use plugins for Adobe products and proofing tools.

Screenshots #1: Two screenshots of Wrike user interface: the first shows a task with a status, a person assigned to it, a brief description and a couple of comments from different people collaborating on the task (one of them has uploaded an image); the second shows a context menu where the user is picking a status from a specific workflow to move the task to.
Screenshots #2: Two more screenshots of Wrike user interface: the first shows a “workload view”: tasks assigned to the team are shown on a timeline, with a summary of working hours for each day for each team member, and the user is rescheduling one of the tasks by dragging it with their mouse; the second shows a “proofing and comparison view” for one of the images attached to the task: on the left, someone is asking the author to change something, and on the right, there’s the updated image.

We think that this is accessibility at its first level. Our product has to be accessible to as many people from different departments as possible.

Wrike is also a single-page application. We want people on different platforms (Mac, Windows, even Linux) to be able to use our app. It’s a web application that can also be a desktop app and provide a user experience that is close to native applications.

We want our product to be accessible to as many people as possible, regardless of disabilities. In the meantime, Wrike is being developed by 20+ different product teams across three countries. We have ~2,500,000 lines of code and 200+ repositories. All accessibility requirements have to be scaled across our distributed teams.

How do we achieve that? How do we measure our progress?

Let’s start with basics

To create a web page, one needs:

  • Some content (obviously)
  • A bunch of HTML
  • CSS
  • JS

If you use HTML properly and it validates, it’s most likely already accessible. A keyboard in the app written in HTML should be working fine. If the correct heading structure is provided and the text color contrast is not messed up, the application will be accessible for users who use screen readers or have color vision deficiency.

Of course, there are caveats, and some features may not be supported in all browsers, but the app should work in general.

To double-check, you can launch Lighthouse or any other tool to get a quick, automatically generated audit report:

Lighthouse report example: A Lighthouse report shows a score of 92 for accessibility. Some issues regarding ARIA attributes usage and contrast between backgrounds and foreground colors are highlighted.
Lighthouse report example

Suppose you have a score of 92 on a pure HTML web page. What does this number tell you about the page? How do you maintain this level of quality as your app grows in size and complexity?

Apps in the wild

On the left and on the right there are browser windows: The left one (single-page application) has three page templates and is able to switch between them without a full page refresh on request The right one (traditional web application) has three pages and loads each page with a full refresh on request
Image © digitalclaritygroup.com

Single-page apps go beyond HTML capacity. We don’t just use HTML and we have a lot of JavaScript code. It’s not only about implementing custom components like dialogs, context menus, or combo boxes, as that’s manageable. There are things that are not fully accessible even in HTML, and we need to go back and add this accessibility support ourselves.

For example, a date input is already included in HTML. But if you try to interact with it using the screen reader, you may find that the actual implementations across different browsers are handled differently. Not all of them are easy to use.

Another problem: When creating a component, you need to ensure that it’s predictable to people regardless of whether they navigate the app with their mouse or keyboard. In the case of a regular select component, it is okay to assume things like “arrow up moves selection up, arrow down moves selection down, enter confirms selection.” But when the component allows users to search by typing text, has autocomplete, and custom controls and interactions on each item of the select list, it can become a nightmare.

Single-page apps work around browser mechanics. Take for example your browser history. If you navigate from one section of the app to another, does it mean that you should handle this action as a history event, allowing users to go back with the browser back button or hotkey? (Most of the time, the answer is yes.) What if a user opens a dialog? Should this action be a history event as well?

Focus management is a total beast, and there are no easy solutions. I won’t elaborate on this topic in this article, but here’s just a couple of recent questions we got about dialogs: How should they work? Should they lock keyboard focus inside or make the “chrome” of the browser reachable by pressing Tab? Should there always be a dedicated close button? Which element should be focused by default when a dialog is opened? We get a lot of questions like this.

Single page apps are developed by people with different backgrounds and focus areas. Accessibility is not the only issue for developers. There are also the issues of security, performance, etc. We need to make sure that everything is working properly, the app is still accessible, and the components are good enough.

You might need a design system for that.

Design system: Why sometimes it’s not enough to have one

You may be asking: “What are you talking about? It’s 2022, everyone has a design system.” I’ll skip the part of explaining the benefits of having one.

Here’s what our design system mockups look like:

A screenshot of a Figma (UI prototyping tool) page with a text input and a list of choices associated with it (a “picker” component) being shown in different states (loading animation, loaded results, results with a message saying there are too many results to display) and themes (light and dark).
Components in Figma

There are just components in many visual states. For some, it may be enough just to have a visual representation of the component to ensure it’s possible to match it with the real app. It also helps UX designers and developers to collaborate. They can see every component in every possible state, find issues upfront, and test it easily.

But if you already have the design system, it makes sense to ask: Are you actually using it?

At Wrike, we found that sometimes if we chose the wrong abstraction or didn’t do something configurable enough in the component, developers will just reinvent the wheel. They keep the visual style but reinvent the implementation. It means that we no longer have control over it.

So we decided to treat our design system as a product in itself and our developers as our customers.

We do the thing that every product company does: Collect and listen to the feedback and try to track it. For example, we have a no-code solution on top of a code metrics database that allows us to know how much of the actual app is built using components. We build reports that show us the dynamics of that usage.

A report created for a particular Wrike feature (in this case, the Board view) listing several metrics (how many components from the common UI library are used — 12, and what is their percentage in templates — 38%), as well as a list of those common UI components used and their relative complexity.
Design system usage report example

We try to make sure that the system is actually solving the developers’ problems and decreasing complexity by providing them with components that are straightforward to use and have sane defaults, not increasing it with complex usage guidelines no one understands or follows.

Another issue that we have is mixing visual and interactive patterns.

For example, here’s a mockup of a context menu:

A screenshot of a context menu that configures the Board view: A section header called “Show on board”, with only one unchecked item “Tasks from subfolders”, then a section divider (horizontal line), under it there’s text “Only [account admins] can edit workflows”, [account admins] is a link to the relevant Help section.

This context menu is opened by clicking on the three-dot button. It contains some menu items and a text card with a link. Everything in this picture could be consistent from a design system standpoint because there is a popup, section header, menu items, and text with links on the bottom. It looks okay and design tokens for typography, colors, and spacing are used correctly, but how should the link in the bottom actually work for keyboard or screen reader users?

We can probably add it to the list of navigable menu items so a user can select with arrow keys or add it as a separate Tab stop. But the question stands: Should it even be possible to have a link like this in a context menu? Should we have an agreement within the design team that they should or shouldn’t use some things in certain contexts?

That’s why it’s important not only to specify the visual style of a component (how it looks) but also its interactions (how it feels).

Another example of mixing interactive and visual patterns is lists:

A side panel with a title “Projects and folders”, below it, a tree view: Talks > Back-end > Front-end > Future “Talks” is marked as focused by a focus ring and as expanded by a down-facing chevron
Folder tree in Wrike

It’s a folder tree, as Wrike is a project management system based on workspaces with a hierarchy of folders and tasks inside each. We need to have some sort of navigation pattern in the tree because it can be very long, and we don’t want users to Tab through hundreds of folders every time they need to go to the next pane of the application.

Then there is the second place that might need this certain type of navigation:

An Inbox view listing several unread messages under the “2 Sep” (September 2nd) header, one of them is focused
Incoming notifications in Wrike

And the third one:

A Kanban board with two columns (“In progress” and “Completed”), first column has two items, the second has one
Board view in Wrike

You might think that it’s better to create one component that would handle everything. But would it be okay from a design perspective? Is it possible to mix visual and interactive?

In our case, we found that it’s better when the system can do both. It works best if it’s possible to split between visual and interactive and also have a combined component.

If you want to dig deeper on this topic, I recommend taking a look at Adobe’s design system, called React Spectrum. There are other examples, but Adobe’s system is a good one as its implementation has an abstract layer (@react-stately), which defines lists, trees, and tables; a browser layer (@react-aria), which works with ARIA attributes and implements keyboard behaviour; and then complete components with a visual design language applied to them (@react-spectrum) that can be plugged in and used in your app.

Automation: How it can help you make a product accessible

There is a preconception that automation doesn’t solve anything when we’re talking about accessibility. Why does it exist? Well, it’s impossible to imitate a real human and hard to automate testing with screen readers, which is one of the trickiest parts of accessibility testing in general.

But I think that this perspective may be wrong. Automation doesn’t have to solve everything, but it surely can help with small, routine tasks that you do every time you build and test a page.

Experts say that 57.38% of Total Issues were detected using automated tests (data from The Automated Accessibility Coverage Report/Deque Systems).

Automation and design systems go together. Here are some tips that can help you to use this combination more efficiently:

  • Use a storybook. If you already have the design system, you probably have some demos (for example, Storybook). It’s easier to test your components in different states there than in your production environment.
  • Enforce strict linting rules and code review to avoid common mistakes in markup (e.g., eslint-plugin-jsx-a11y).
  • After you’ve run manual audits in Lighthouse or axe DevTools, write automated tests (e.g., with axe-core’s Selenium integration).

Growth issues

Do the tools that I’ve mentioned solve all problems? I think that they don’t. There is another angle of this problem — growth. As teams grow and the product becomes more complicated, you start to notice that, even with automation and design systems, there still will be a lot of chaos.

Here are some issues we faced at Wrike:

  • Centralized (authoritarian) approaches (e.g., “All components should be built or reviewed by the UI Kit internal team”) stop working, teams need independence.
  • Technology and automation does not solve organizational issues. If there is a legacy app or component and nobody knows what to do with it or even wants to do anything with it, technology can’t help the lack of understanding or motivation.
  • “Gut feeling” is not a metric of quality. Without metrics, quality doesn’t scale. In a large organization going through a large initiative, it’s hard to understand where you are right now on your way, so you need metrics and transparency.

I think that you might need not only a technological solution like a design system or an automation framework but a culture. Working with people is not only about lines of code or frameworks that you use. It’s important that these people with different opinions and different views on the world feel connected and supported.

To do that you might need business values.

Illustration: a silhouette of a person with their arms wide open in a circle (one of the symbols of digital accessibility) which is wrapped aroung a DNA helix
Is accessibility a part of your company DNA?

When one starts talking about business values, it often sounds like nonsense, companies praising themselves in ways that look good in an HR playbook, right? I still think that it’s worth asking your management team if they really care about accessibility. It’s likely that no one will tell you that they don’t. But you may keep asking questions.

Here are some of them:

  • Do we ask people with disabilities for feedback?
  • Is accessibility in our quarterly goals?
  • Is there a dedicated accessibility team or a subject matter expert?
  • Do we have plans to hire employees who’ll be responsible for accessibility?
  • Do we have a plan to educate people on the team?
  • Do our designers and engineers collaborate on that area?

When you ask those questions, you might get the answer: “We don’t do it because we don’t have such customers.” But it’s Сatch-22 — a problem in which the solution is inherently blocked by the circumstance of the problem.

You don’t make the content accessible because you don’t have the customers. You don’t have the customers because you don’t make the content accessible.

For example, if you want to work with a university in a country where accessibility is mandatory, you won’t get the contract. There are also many companies that want the products they use to be accessible for no specific legal reason but simply because they care about their employees.

Steps to take

Express your commitment to accessibility. There are a couple of ways to do it. Put it on the company website or talk about it with clients. It is important to make this message transparent and visible to the whole company. This process will not be scalable unless it is in the DNA of the company.

Hire people who can be accountable for accessibility, from UX concepts to customer support. It doesn’t mean that these people will be responsible for everything and will have to control everything. These are the people you can come to, who can mentor other team members and validate their own initiatives.

Provide opportunities for all employees to gain experience and education. Try to make small changes to certain components of the design system or some new area of the product before scaling the approach to the whole product. In order to grow, people need space to experiment and feedback. If you’re constantly telling your engineers and designers that the product is not accessible and therefore bad, and at the same time require that it becomes accessible in an instant, it won’t motivate anyone in the team but burn them out.

Validate your progress with real people. For example, set up a small community of users with disabilities (believe me, you will find them quickly if you just ask) and try to talk with them regularly to understand where you are in the process.

Set process-related goals. Instead of “80% of UI components are accessible by 2023,” try “80% of teams know and use the accessibility design and testing principles and have them in their Definition of Done by 2023.”

Acknowledge you’re on a journey that will take time. If we’re talking about a product that was started in the mid-2000s, the journey to being fully accessible may take years. But it will get better eventually, and it’s totally worth it!

Tips for development teams

Make features accessible from the start. When you start working on a big feature, the UX concept stage is the right time to start discussing accessibility. The UX concept stage is when problems can be identified and solved easily. Use that time.

If you have prototypes built in code, it’s even better, because you can test it on real users before the development stage. The “fix it in post” approach might work for you too, but it will cost you much more. Fixing something that was not built with keyboard or screen reader users in mind without breaking the user experience you’ve already designed for mouse or touch may be hard.

Leverage your legacy. You might have a ton of old UI code (and lots of accessibility issues), but don’t be discouraged. It also means that your team has a whole lot of experience and a lot of things to start applying new principles to. Apply what you already know and learn on the go.

Fail gloriously. Some things will be impossible to fix on the first attempt. Keep trying and don’t be afraid to say that something’s going wrong. It is even possible that you’ll have to rebuild some parts of the product from scratch. Remember that it’s a marathon, not a sprint.

P.S. Accessibility is not just a trend, metrics in Lighthouse, ADA or any other law, ARIA and WCAG. Focus on cross-functional approach (from design to development to testing) and people, not just coding standards. If you want to start building accessible components, I recommend reading “A Complete Guide To Accessible Front-End Components” by Smashing Magazine.

--

--

Alex Chudesnov
Wrike TechClub

A senior front-end developer at Wrike who cares a lot about digital accessibility.