Accessibility-flavored React components make your design system delicious!

A presentation at Accessibility Chicago in October 2020 in by Kathleen McMahon

Slide 1

Slide 1

Accessibility-flavored React components make your design system delicious!

Welcome everyone! I’m Kathleen McMahon and I’m here today to show how Accessibility-flavored React components make your design system delicious!

Before we begin, let’s get some details out of the way.

Slide 2

Slide 2

My slide deck will be posted on Notist, that’s https://noti.st/resource11, including links to resources I briefly touch upon. The full URL will be available later today on Twitter.

Slide 3

Slide 3

You can follow me at. Resource11 on Twitter, Instagram, and GitHub.

Now… here’s an outline of what we’ll be covering today.

Slide 4

Slide 4

Why accessibility first? Design systems are a cookbook. Design systems and React Icons, Buttons, Inputs, disclosure patterns Documentation

Slide 5

Slide 5

Let’s back up so I can introduce myself better…

Slide 6

Slide 6

I’m a Principal Engineer at CarGurus

Slide 7

Slide 7

[image] Me on a cyclocross bike, hopping over barriers and riding through mud.

And… I race bikes. Very badly.

Slide 8

Slide 8

[image] Me on a cyclocross bike, in Spam, Ninja Turtle, Nerds candy box, Medusa costumes

Mostly you’ll see me in costume, racing two laps to your six, at the back of the pack, on a singlespeed.

Mostly. Unless something happens.

Slide 9

Slide 9

[image] Big Bird kicks open the apartment door

Like… a pandemic kicking in our doors. Then your racing season is postponed.

Slide 10

Slide 10

[image] Pictures of me on a cyclocross bike, in costume

So while I’m an engineer, and a super slow bike racer…

Slide 11

Slide 11

[image] A group of dinousaurs grazing, lift their heads up in unison

I’m also a dev dinosaur. And I find it fascinating see…

Slide 12

Slide 12

[image] Amiga computer from the 1990s

…how far we’ve come from the tools we had for computing…

Slide 13

Slide 13

[image] Photoshop 3 user interface

And software…

Slide 14

Slide 14

[image] Macromind director user interface

And software…

Slide 15

Slide 15

[image] box of older storage tech, including 3.5" floppy disks, Zip disks, Bernoulli disks, SyQuest disks

Storage…

Slide 16

Slide 16

[image] Arrangement of all my software reference books from the 1990s through early 2000s

…and reference.

Slide 17

Slide 17

[image] Netscape logo

While our browser choices were minimal… Netscape, anyone?

Slide 18

Slide 18

…our stack has stood the test of time. HTML, CSS, and JavaScript

Slide 19

Slide 19

JavaScript Framework of the week

Fast forward to now and the industry is moving at a really fast pace…

Slide 20

Slide 20

[image] Stanley Spadowski shouts "OPEN WIDE!" and douses boy with a fire hose

…and it can feel overwhelming to keep up, much less find the place where you can thrive.

Especially if you have both design and engineering skills, and love that fundamental stack.

But fear not!

Slide 21

Slide 21

[image] Person in inflatable dinosaur costume flips into a raft floating on a pond and claps with glee

Dinosaurs are always the hotness.

Those old-school HTML/CSS/JavaScript skills are highly valuable and transferrable — no matter which framework you use — and they will give you an edge in the industry where the div has become the reluctant king.

Slide 22

Slide 22

So before working at CarGurus, I was the Tech Lead for O’Reilly Media’s design system.

I learned a lot about streamlining component libraries during my time there.

Slide 23

Slide 23

If you’ve ever worked on a design system, you know there are a lot of things to consider.

Slide 24

Slide 24

And great design systems combine two key factors: user experience, and END user experience.

Slide 25

Slide 25

[image] woman attempting to arrange 10 squirming kittens in a straight line, with varied success

However. Similar to herding cats, creating a great design system can be tough with so many moving parts.

If you are rebooting a design system, will have to choose what to tackle first.

If your design system team is small, you have to be very strategic. For example…

Slide 26

Slide 26

If any business logic in the components, your first priority should be to extract that out, and build with accessibility in mind.

Fix your colors, your components, then reboot your docs.

Slide 27

Slide 27

You may ask, why accessibility first?

Slide 28

Slide 28

Well, our users have varied needs, and… because so often, that’s what is handled last.

Which sends a poor message to our users.

Slide 29

Slide 29

If you’ve read the WebAIM Million report, the results are depressing

Slide 30

Slide 30

With the amount of errors found on pages…

Slide 31

Slide 31

…Unlabeled inputs

Slide 32

Slide 32

…and unnecessary ARIA attributes, we’re making the web worse in the name of good intentions.

Slide 33

Slide 33

While we have things like the Web Content Accessibility Guidelines to follow which is a really low bar, we’ve been missing the mark in the industry when it comes to making sure all our users can use our apps.

Slide 34

Slide 34

Imagine, though, if you had accessibility baked into some commonly-used components.

A design system is the perfect place for this.

Slide 35

Slide 35

I like to say your design system is a cookbook

Slide 36

Slide 36

Cookbooks have personality.

My Mom is a serious fan of cooking, and lately I’ve been enjoying digging through the cookbooks she’s collected over the years to read how recipes evolved over time.

If you take a look at some of the cookbooks published in the 1940s-60s…

Slide 37

Slide 37

[image] Betty Crocker cookbook from the mid 20th century, "Why nearly 9 million women cherish this cookbook" prominently featured as a callout

And look past the outdated views…

Slide 38

Slide 38

[image] Betty Crocker cookbook from the mid 20th century displaying various dishes

You’ll find interesting recipes…

Slide 39

Slide 39

[image] Shrimp and lime jello mold, plated with apple slices

Questionable food combinations that included Jello and shellfish.

Slide 40

Slide 40

[image] Meats and poultry cookbook reference page

…and an impressive level of detail paid to the structure of every single part of the cooking process.

Slide 41

Slide 41

[image] Soups and sauces reference page

…and an impressive level of detail paid to the structure of every single part of the cooking process.

Slide 42

Slide 42

[image] Vegetables reference page

…and an impressive level of detail paid to the structure of every single part of the cooking process.

Slide 43

Slide 43

[image] Desserts reference page

…and an impressive level of detail paid to the structure of every single part of the cooking process.

Slide 44

Slide 44

[image] Table settings and enertaining reference page

There’s even a section on table settings and entertaining!

This is very similar to how a design system works.

Slide 45

Slide 45

Now what does that have to do with React?

Slide 46

Slide 46

There’s always some debate about how using a Javascript framework creates inaccessible apps

Slide 47

Slide 47

Yet… React fully supports building accessible websites, by using standard HTML/CSS techniques.

Slide 48

Slide 48

A better way to think of React is to consider it a kitchen utensil. It’s not the only utensil in your kitchen.

Slide 49

Slide 49

You are the cook

In my opinion, It’s up to the developer to have that standard HTML/CSS/JavaScript and accessibility knowledge to be able to leverage a utensil correctly.

And that includes React.

Slide 50

Slide 50

That said, if your developers are unsure how to start building inclusive apps,

Empower with your design system.

Build some features into your components to help them along.

Slide 51

Slide 51

Then you can start celebrating when your co-workers make those apps accessible without you having to ask for it

Slide 52

Slide 52

Components are your tried and true recipes

Slide 53

Slide 53

WCAG is Your reference material

Slide 54

Slide 54

And creating a component is like following a recipe

Slide 55

Slide 55

First, you Start with high-quality ingredients (semantic HMTL)

Slide 56

Slide 56

Mix in seasonings (just a touch of ARIA)

Slide 57

Slide 57

Follow the directions

Slide 58

Slide 58

And provide helpful hints as best practices

Let’s take those principles and apply them to some components…

Slide 59

Slide 59

Let’s talk Icons.

Slide 60

Slide 60

Icons can be informative or decorative

Informative icons need to be paired with descriptive text to be perceivable by screen readers

Decorative icons need to be hidden from screen readers, because they don’t add significant value to your app

Slide 61

Slide 61

But wait! Icons can be interpreted in so many different ways!



True.

Slide 62

Slide 62

For example, you may see the heart symbol used to favorite something in an app

Slide 63

Slide 63

Other apps may use a star. This leaves way too much up to interpretation by the user.

Slide 64

Slide 64

Ideally, you should be pairing any icons you use with visible text.

Slide 65

Slide 65

This way, users will have a clear context on its purpose.

Of course, there is a big BUT in here, and depends on the buy in you get for icon usage in your designs. And whether you can get a design approved that uses a label paired with an icon like this.

That said, in general terms…

Slide 66

Slide 66

There is more than one way to create an accessible icon. Two of the most recent ways are… SVGs and icon fonts.

At O’Reilly, we initially used SVG icons in our design system combined into a sprite sheet, yet we ran into some problems when we started testing.

Slide 67

Slide 67

[image] Natalie Portman, weeping in the corner

We discovered a bug in Safari on High Sierra, where VoiceOver would announce every single one of those 100 or so icons in that sprite sheet.

It made me sad. So…we had to think fast to find a different solution.

Slide 68

Slide 68

We converted all our icons into a font set for the time being, and chose to revisit SVG icons later, since that HighSierra bug has now been fixed.

Let’s go over an example of how we make an accessible icon component using semantic HTML and the icon font technique.

Slide 69

Slide 69

This is what you typically see as an icon font pattern in the wild, but it’s not accessible.

Slide 70

Slide 70

This is an accessible icon pattern. Let’s break it down.

Slide 71

Slide 71

The span containing our icon font

Slide 72

Slide 72

Has been sprinkled with a pinch of aria-hidden=”true”, to hide the icon font from screen readers

Slide 73

Slide 73

This second span contains the descriptive name for our icon

Slide 74

Slide 74

And has a visuallyHidden class added to it. This removes the visual presentation of that text, yet keeps that text available to screen readers.

Slide 75

Slide 75

In the wrapping span, we use a CSS class to convert the span’s native display property from inline to inline-block.

This allows us to support margin/padding customization on all four sides of the element

Slide 76

Slide 76

Notice that spans are being used for all three elements. This is on purpose for when we pair this component with a button

Slide 77

Slide 77

Now before we refactor this pattern into React, let’s consider whether this icon is informative or decorative?

Slide 78

Slide 78

If our icon is informative, we keep this markup as is, because informative icons should announce

Slide 79

Slide 79

If our icon is decorative, we’d add this aria-hidden attribute to the wrapping span to ensure the entire group is not announced to a screen reader.

Slide 80

Slide 80

Now that we have an accessible icon pattern, let’s pop this into a functional component and convert this to JSX

Slide 81

Slide 81

Change class to className, convert that “true” string to a boolean value, and self close that empty span element

Slide 82

Slide 82

Now this is a static icon component in JSX.

Let’s make this component more flexible

Slide 83

Slide 83

…and expand that syntax to support three incoming props: iconHidden, iconName, iconTitle and add some guardrails

Slide 84

Slide 84

[image] Moody view of empty bowling lanes

It’s important to create ‘guardrails’ for your components so you can be sure that devs are always using the accessibility features you’ve mixed in.

For our icon component, we added three guardrails.

Slide 85

Slide 85

The first guardrail we’ve set up is a check if the iconName the dev passes in to the component is in our icon library.

If the icon doesn’t exist in the library, the component doesn’t render in the app.

Slide 86

Slide 86

The second guardrail we’ve set here is to ensure if the dev doesn’t pass in descriptive text to that iconTitle prop, the icon’s default name is always exposed a fallback

Slide 87

Slide 87

The last guardrail is the iconHidden prop.

If the dev passes in iconHidden true, the containing span’s will render in the DOM with an aria-hidden=”true” attribute

If no iconHidden prop is passed in, the aria-hidden attribute isn’t attached to the wrapping span at all.

Slide 88

Slide 88

We’re guaranteeing that the icon will read out to screen readers no matter what, unless the dev purposely specifies otherwise by passing in iconHidden value

This true or null pattern works well with HTML attributes that only need to be added if the value exists. aria-hidden is one of those

Slide 89

Slide 89

You may still be saying… what about SVGs? What if I haven’t rolled my own icon set?

There are great options out there to do this with SVGs as well.

Like…

Slide 90

Slide 90

Fontawesome is still a great option for this.

Slide 91

Slide 91

In fact, Fontawesome now has an official React component you can use.

Slide 92

Slide 92

And it has been built with accessibility in mind.

Slide 93

Slide 93

It’s pretty straightforward to use this component…

Slide 94

Slide 94

…and it adds the right properties for you under the hood by default. There is a slight bug if you want to use the component as a standalone informative icon.

Slide 95

Slide 95

Say you want the icon to announce as a beverage in this case…

Slide 96

Slide 96

…and you pass in an ariaLabel prop

Slide 97

Slide 97

Yes that aria-label will render. But!

Slide 98

Slide 98

Because the SVG element already has an aria-hidden attribute attached, that aria label will do nothing here.

Slide 99

Slide 99

However. You can get around this by using the Icon component we built and swapping out that span using the CSS class…

Slide 100

Slide 100

…and swapping in the FontAwesome component

Slide 101

Slide 101

…then you can leverage that visually-hidden span to make your icon informative.

Slide 102

Slide 102

Buttons

Slide 103

Slide 103

Buttons perform an action on the page

Buttons should look and act like a button

Buttons get screen reader and keyboard functionality for free

Slide 104

Slide 104

Our high quality ingredient here is the button element.

Slide 105

Slide 105

We sprinkle in an aria-label to support instances where we have multiple buttons with the same name on the page to give context to screen reader users. Like those times when you have 10 ‘read more’ buttons on the page. With this label, you know that this button allows you to read more about dinosaurs.

Slide 106

Slide 106

It’s important when using an aria-label like this to match the first words in the aria-label with the button text to support voice recognition software

Slide 107

Slide 107

If your app needs to support localization, Adrian Roselli just wrote a great article with a different pattern that uses the aria-describedby attribute. That article will be shared in the resources later.

Slide 108

Slide 108

This is an accessible button in JSX

Slide 109

Slide 109

If we want to support button text with icons, we mix in our Icon component

Slide 110

Slide 110

And we wrap button contents in a span for positioning

Note: we’re using inline level elements inside buttons

No nesting buttons or other controls inside a button’s children

That’s not valid HTML

Slide 111

Slide 111

The JSX is popped into the Component’s render method, and we add props, onClick handler and disabled button support

Slide 112

Slide 112

The one guardrail we add ensures if no iconName is passed in, no icon will render in the button

Slide 113

Slide 113

Inputs

Slide 114

Slide 114

Inputs need labels and error messages

Labeled inputs give all users more context

Slide 115

Slide 115

Placeholders are NOT labels

Avoid using placeholders instead of labels, users will lose context

Hard to style across browsers

Placeholders aren’t auto translated

Slide 116

Slide 116

We’ve built our input components to minimize horizontal scrolling, and stack our labels above the input, error messages below the input to support screen magnification users.

You can also place the error message right below the label for even better discoverability

Slide 117

Slide 117

This is an accessible input pattern. It’s a bit hard to read so let’s zoom in.

Slide 118

Slide 118

We start with our high-quality ingredients



Slide 119

Slide 119

Pairing labels and error messages to the input

Slide 120

Slide 120

And in JSX we associate the label with the input by pairing the label’s htmlFor prop value with the input id value

Slide 121

Slide 121

Mix in key ARIA spices for validation

Aria-invalid, aria-required, and the pair the aria-describedby and error text id values

Slide 122

Slide 122

We also add an aria-live=“polite” to error message span to announce errors to screen readers

Slide 123

Slide 123

To make this more flexible… mix in disabled attribute support

onChange and OnKeypress synthetic events to capture keyboard actions

Add true/null handling for the boolean props

Slide 124

Slide 124

Add your guardrails. If the dev doesn’t pass in a label, the whole input won’t render. Neither will the icon.

This will help guide the developer to follow best practices when implementing a component, and it will become second nature

Slide 125

Slide 125

Same goes for the error handling, if the developer doesn’t pass in both the invalid prop and the error message prop to the component, it won’t render.

Slide 126

Slide 126

Disclosure widgets. A disclosure widget is an interactive pattern that uses a button to control the visibility of a section of content.

Slide 127

Slide 127

This pattern is great, because it’s flexible, keyboard/mouse operable, and its base functionality is very similar for more than one type of interactive component.

Slide 128

Slide 128

Some common patterns are nav menus, toggle tips, and settings disclosures.

Others types of widget patterns are custom select menus and autocompletes.

We won’t be talking about those today because — in addition to enter/spacebar/escape keys — these two patterns also need up/down arrow keys and the home/end key support.

Slide 129

Slide 129

One important thing to note. A tooltip is NOT a toggle tip, the interactions are different.

A tooltip’s interactivity revolves around hovering over the tool tip and maybe focusing on it with a keyboard.

Slide 130

Slide 130

This can be problematic for any sort of touch device which doesn’t support hover, like a non-mouse pointer or eye tracker.

Also, anyone using a screen magnifier may accidentally dismiss a tooltip by moving their field of view and hovering away.

Slide 131

Slide 131

The three primary interactions we will focus on are the space bar/Enter key — which comes natively when you use a button to open the disclosure — the ESC key, and mouse clicks.

Slide 132

Slide 132

For special cases, like a search menu that toggles into view, you can optionally send focus to the first item in the open container.

Slide 133

Slide 133

Let’s take a look at a disclosure widget pattern in this Codesandbox

Slide 134

Slide 134

Documentation. Those massive design systems out there definitely have some drool-worthy patterns for us to dream about. If your team is small, showing examples of the many ways your component can be used is a good first step.

Slide 135

Slide 135

When we were rebooting the docs, we used Gatsby for our style guide to leverage the power of MDX, and Storybook to document our component playground.

Slide 136

Slide 136

and deployed static instances of our docs using Zeit’s Now…

Slide 137

Slide 137

…otherwise known as Vercel these days.

Slide 138

Slide 138

I want to touch upon Storybook for a moment.

It’s a great way to Sandbox your components in isolation, and play with UI logic without the complexities of business logic.

Supports MDX as well. The Accessibility addon is a must here.

Slide 139

Slide 139

Uses axe-core engine, does a quick audit of your components

Identifies errors, tells you how serious they are, and

Gives you steps to fix them before you start your manual accessibility testing.

Slide 140

Slide 140

When documenting components, you should add helpful hints to help developers choose how to implement your components. For example, how to make an informative icon. 


Slide 141

Slide 141

Or a decorative icon


Slide 142

Slide 142

Be sure to add prop tables for your components, so your developers know which prop does what, and whether it’s required.

Slide 143

Slide 143

Component dos and don’ts are essential.

Slide 144

Slide 144

Dedicate a page to accessibility resources and links. The WCAG success criteria is really intense to parse.

If you have curated any articles that help explain how to implement common accessibility patterns, add those to your docs.

Slide 145

Slide 145

So to wrap up…

Slide 146

Slide 146

Our users are diverse

Slide 147

Slide 147

Your Design system is a cookbook

Slide 148

Slide 148

Cookbooks have Personality

Slide 149

Slide 149

React is a kitchen utensil

Slide 150

Slide 150

You are the cook

Slide 151

Slide 151

Components are your tried and true recipes

Slide 152

Slide 152

WCAG is your reference material

Slide 153

Slide 153

Document, document, document. And remember…

Slide 154

Slide 154

[image] Person in inflatable dinosaur costume flips into a raft floating on a pond and claps with glee

Dinosaurs are ALWAYS the hotness

Slide 155

Slide 155

Thank you.

Slide 156

Slide 156

https://noti.st/resource11

Slide deck posted after the talk @resource11 Twitter | Instagram | GitHub