Making Single Page Apps Accessible

A presentation at NDC Sydney 2024 in February 2024 in Sydney NSW, Australia by Jess Budd

Slide 1

Slide 1

Making Single Page Apps Accessible jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 2

Slide 2

JESS BUDD - Senior software engineer - Web accessibility nerd - Lover of lego jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 3

Slide 3

jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 4

Slide 4

TIM BERNERS-LEE Inventor of the World Wide Web jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 5

Slide 5

The power of the web is in its universality. Access by everyone, regardless of disability is an essential aspect. - Tim Berners-Lee jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 6

Slide 6

It doesn’t have to be this way. jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 7

Slide 7

Nothing in React prevents us from building accessible web apps - Leslie Cohn-Wein, Netlify jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 8

Slide 8

jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 9

Slide 9

jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 10

Slide 10

… @jessbudd4 jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 11

Slide 11

Low hanging does not mean low impact. - Samuel Proulx, Accessibility Evangelist, blind since birth jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 12

Slide 12

What is accessibility?

Slide 13

Slide 13

Removing barriers to using your website @jessbudd4 jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 14

Slide 14

Accessibility benefits all of us. jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 15

Slide 15

Image credit: Microsoft Inclusive Design jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 16

Slide 16

Accessibility: otherwise known as A11y jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 17

Slide 17

Visual •285 million worldwide •Blindness •Colour blindness •Low or tunnel vision jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 18

Slide 18

Auditory •1 in 6 Australians •Profound deafness •Hard of hearing jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 19

Slide 19

Motor •Loss of limbs •Chronic pain conditions •Cerebral Palsy jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 20

Slide 20

Cognitive •Intellectual impairments •Learning disabilities •Dementia jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 21

Slide 21

Be kind to your future (old) self. jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 22

Slide 22

Web Content Accessibility Guidelines

Slide 23

Slide 23

WCAG (wuh-cag) jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 24

Slide 24

WCAG (wuh-cag) jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 25

Slide 25

Perceivable Operable Understandable Robust jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 26

Slide 26

• Level A: bare minimum • Level AA: industry standard to aim for • Level AAA: highest standard jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 27

Slide 27

HTML

Slide 28

Slide 28

Use native browser elements and controls jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 29

Slide 29

Why does it matter? jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 30

Slide 30

jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 31

Slide 31

Image credit: Microsoft Inclusive Design jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 32

Slide 32

Accessibility is good for SEO jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 33

Slide 33

If a screen reader can’t understand your content, neither can Google. jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 34

Slide 34

// Inaccessible card component <template> <div class=”card”> <div>{{productName}}</div> <div>{{productDescription}}</div> <div v-on:click=”doSomething”> {{buttonText}} </div> </div> </template> jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 35

Slide 35

Click to edit jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 36

Slide 36

<CustomComponent> jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 37

Slide 37

// More accessible card component <template> <li :class=”card”> <h2>{{productName}}</h2> <p>{{productDescription}}</p> <button v-on:click=”doSomething”> {{buttonText}} </button> </li> </template> jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 38

Slide 38

Divs are not buttons. jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 39

Slide 39

<div tabindex=”0” role=”button” v-on:keyup={handleKeyUp} v-on:click={handleClick}> {{buttonText}} </div> jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 40

Slide 40

<div tabindex=”0” role=”button” v-on:keyup={handleKeyUp} v-on:click={handleClick}> {{buttonText}} </div> jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 41

Slide 41

<div tabindex=”0” role=”button” v-on:keyup={handleKeyUp} v-on:click={handleClick}> {{buttonText}} </div> jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 42

Slide 42

<button v-on:click={handleClick}> {{buttonText}} </button> jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 43

Slide 43

Give buttons some love jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 44

Slide 44

WCAG success criteria: 1.3.1 - Info and relationships (A) 2.1.1 - Keyboard (A) 4.1.2 - Name, Role, Value (A) jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 45

Slide 45

FORMS

Slide 46

Slide 46

Inputs must have labels. Labels must be linked. jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 47

Slide 47

// label not linked to input <label> Lego character: </label> <input type=”text” K N A L B , t x e Edit t name=”character” /> jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 48

Slide 48

// explicitly linked label to input <label for=”uniqueId”> Lego character: </label> <input id=”uniqueId” R E T C A R A H C O Edit text, LEG type=”text” name=”character” /> jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 49

Slide 49

How can I make sure my IDs are unique? jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 50

Slide 50

import { v4 as uuid } from “uuid”; <script> data() { return { id: ${this.name}-${uuid()} } } }; </script> <template> <div class=”a11y-input”> <label v-bind:for=”uniqueId”>{{ label }}</label> <input v-bind:id=”uniqueId” v-bind:name=”name” type=”text” /> </div> </template> jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 51

Slide 51

import { v4 as uuid } from “uuid”; <script> data() { return { id: ${this.name}-${uuid()} } } }; </script> <template> <div class=”a11y-input”> <label v-bind:for=”uniqueId”>{{ label }}</label> <input v-bind:id=”uniqueId” v-bind:name=”name” type=”text” /> </div> </template> jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 52

Slide 52

import { v4 as uuid } from “uuid”; <script> data() { return { id: ${this.name}-${uuid()} } } }; </script> <template> <div class=“a11y-input”> <label v-bind:for=”uniqueId”>{{ label }}</label> <input v-bind:id=”uniqueId” v-bind:name=”name” type=”text” /> </div> </template> jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 53

Slide 53

Implicit linking? jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 54

Slide 54

// implicitly linked label to input <label> Lego character: <input type=”text” name=”character” R E T C A R A H C O Edit text, LEG /> </label> jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 55

Slide 55

What if the design doesn’t have labels? jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 56

Slide 56

// label hidden with css is still announced <label class=”sr-only” for=”legoCharacter”> Lego character: </label> <input id=”legoCharacter” type=”text” name=”character” /> jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 57

Slide 57

// visually hidden, but accessible to screen readers .sr-only { clip: rect(0 0 0 0); clip-path: inset(50%); height: 1px; width: 1px; overflow: hidden; position: absolute; white-space: nowrap; } jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 58

Slide 58

WCAG success criteria: 3.3.2 - Labels or instructions (A) jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 59

Slide 59

Can I use placeholders instead? jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 60

Slide 60

Placeholders are not labels jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 61

Slide 61

…or suitable help text jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 62

Slide 62

WCAG success criteria: 3.3.2 - Labels or instructions (A) 3.3.5 - Help (AAA) jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 63

Slide 63

… jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 64

Slide 64

Implicitly linked touch target jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 65

Slide 65

Explicitly linked touch target jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 66

Slide 66

WCAG success criteria: 2.5.8 - Target size (minimum) (AA) 2.5.5 - Target size (AAA) jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 67

Slide 67

Autocomplete jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 68

Slide 68

<label for=”uniqueId”> First name: </label> <input id=”uniqueId” type=”text” name=”firstName” autocomplete=”given-name” /> jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 69

Slide 69

WCAG success criteria: 1.3.5 - Identify input purpose (AA) jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 70

Slide 70

FOCUS STYLES

Slide 71

Slide 71

Image credit:Access Guide jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 72

Slide 72

Safari: Firefox: Chrome: jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 73

Slide 73

Removing the focus outline is like removing the wheelchair ramp from a school because it doesn’t fit the aesthetic. - David Gilbertson jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 74

Slide 74

Meme where am I jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 75

Slide 75

Screen shot of page with masses of ??? links and question marks jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 76

Slide 76

/* don’t just remove */ :focus { outline: none; } / replace with something! */ :focus-visible { / branded focus styles here */ outline: 2px dotted #10ffc3; } jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 77

Slide 77

WCAG success criteria: 1.4.11 - Non-text contrast (AA) 2.4.7 - Focus visible (AA) 2.4.13 - Focus appearance (AAA) jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 78

Slide 78

Make it big and stand out jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 79

Slide 79

Outlines are best jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 80

Slide 80

Offset outlines even better *:focus-visible { outline: 2px dotted #10ffc3; outline-offset: 2px; } jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 81

Slide 81

ROUTING

Slide 82

Slide 82

Traditional multi-page app behaviour Builds the page jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 83

Slide 83

Single page app behaviour Builds the page jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 84

Slide 84

  1. Update page title 2. Manage keyboard focus jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 85

Slide 85

PAGE TITLES

Slide 86

Slide 86

PAGE TITLE jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 87

Slide 87

LEGO IS FUN!

<head> MY FAVE LEGO MORE LEGO <meta charset=”utf-8”> <title>Lego is fun!</title> <link rel=”stylesheet” href=”style.css”> </head> jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 88

Slide 88

jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 89

Slide 89

// react functional component import { useEffect } from “react” export const BlogPost = () =>{ useEffect(() => { document.title = “Trolls lego is the best” }) return( <> <h1>A heading</h1> <p>Some page content</p> </> ) } jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 90

Slide 90

// vue page level component <script> export default { name: “Blog post”, mounted() { document.title = “Trolls lego is the best”; }, }; </script> jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 91

Slide 91

const router = new VueRouter({ routes: [ { path: ‘/blog’, component: BlogComponent, meta: { title: “My awesome Lego blog” } }, { path: ‘/about’, component: AboutComponent, meta: { title: “About Lego Lover” } } ] }); jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 92

Slide 92

router.beforeEach((to, from, next) => { document.title = to.meta.title || ‘${defaultTitle}’; next(); }); jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 93

Slide 93

// use helmet to update additional meta data at the same time import {Helmet} from “react-helmet”; export const SignupForm = () =>{ return( react-helmet <Helmet> <title>{meta.title}</title> <meta name=”image” content={meta.image} /> <meta name=”description” content={meta.description}/> <meta name=”og:title” content={meta.title}/> <meta name=”og:description” content={meta.description}/> <meta name=”og:image” content={meta.image}/> </Helmet> vue-meta ) } jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 94

Slide 94

Click to edit jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 95

Slide 95

WCAG success criteria: 2.4.2 - Page titled (A) jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 96

Slide 96

FOCUS MANAGEMENT

Slide 97

Slide 97

Option 1: Fake a traditional navigation jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 98

Slide 98

Option 2: Optimise navigation jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 99

Slide 99

Tabindex tabindex=”0” // makes element focusable in tab/DOM order tabindex=”-1” // makes elements focusable only via scripting tabindex=”5” // danger Will Robinson! jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 100

Slide 100

Tabindex tabindex=”0” // makes element focusable in tab/DOM order tabindex=”-1” // makes elements focusable only via scripting tabindex=”5” // danger Will Robinson! jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 101

Slide 101

Tabindex tabindex=”0” // makes element focusable in tab/DOM order tabindex=”-1” // makes elements focusable only via scripting tabindex=”5” // danger Will Robinson! jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 102

Slide 102

Tabindex tabindex=”0” // makes element focusable in tab/DOM order tabindex=”-1” // makes elements focusable only via scripting tabindex=”5” // danger Will Robinson! jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 103

Slide 103

import React, { useEffect, useRef } from ‘react’; const PageComponent = () => { const h1Ref = useRef(null); useEffect(() => { if (h1Ref.current) { h1Ref.current.focus(); } }, []); return ( <h1 ref={h1Ref} tabIndex=”-1”>Lego is the best!</h1> // Rest of the component ); }; jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 104

Slide 104

import React, { useEffect, useRef } from ‘react’; const PageComponent = () => { const h1Ref = useRef(null); useEffect(() => { if (h1Ref.current) { h1Ref.current.focus(); } }, []); return ( <h1 ref={h1Ref} tabIndex=”-1”>Lego is the best!</h1> // Rest of the component ); }; jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 105

Slide 105

import React, { useEffect, useRef } from ‘react’; const PageComponent = () => { const h1Ref = useRef(null); useEffect(() => { if (h1Ref.current) { h1Ref.current.focus(); } }, []); return ( <h1 ref={h1Ref} tabIndex=”-1”>Lego is the best!</h1> // Rest of the component ); }; jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 106

Slide 106

jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 107

Slide 107

// don’t show focus for headings H1:focus-visible { outline: none; } jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 108

Slide 108

MODALS

Slide 109

Slide 109

jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 110

Slide 110

Modals are actually the boss battle at the end of web accessibility. - Rob Dodson, host of A11yCasts jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 111

Slide 111

jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 112

Slide 112

<script> export default { methods: { showDialog() { this.$refs.dialogRef.showModal(); }, closeDialog() { this.$refs.dialogRef.close(); }, }, }; </script> <template> <dialog ref=”dialogRef”> <button v-on:click=”closeDialog”>Close</button> <p>Modal content</p> </dialog> <button v-on:click=”showDialog”>Show the dialog</button> </template>

jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 113

Slide 113

<script> export default { methods: { showDialog() { this.$refs.dialogRef.showModal(); }, closeDialog() { this.$refs.dialogRef.close(); }, }, }; </script> <template> <dialog ref=”dialogRef”> <button v-on:click=”closeDialog”>Close</button> <p>Modal content</p> </dialog> <button v-on:click=”showDialog”>Show the dialog</button> </template>

jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 114

Slide 114

jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 115

Slide 115

// send focus to non-destructive button <dialog> <h2>Delete Conversation</h2> <p>Are you sure you want to delete this conversation? This action cannot be undone.</p> <button>{{destructiveAction}}</button> <button autofocus>{{cancel}}</button> </dialog> jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 116

Slide 116

:modal { border: 5px solid red; background-color: yellow; box-shadow: 3px 3px 10px rgb(0 0 0 / 50%); } ::backdrop { background: rebeccapurple; opacity: 0.75; } jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 117

Slide 117

:modal { border: 5px solid red; background-color: yellow; box-shadow: 3px 3px 10px rgb(0 0 0 / 50%); } ::backdrop { background: rebeccapurple; opacity: 0.75; } jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 118

Slide 118

html inert attribute jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 119

Slide 119

inert 102 jessbudd@bsky.social 102 jessbudd@front-end.social 112 15.5 jessbudd44 19 @jessbudd @jessbudd4

Slide 120

Slide 120

WCAG success criteria: 2.4.3 - Focus order (AA) jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 121

Slide 121

TESTING

Slide 122

Slide 122

Automated + Manual jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 123

Slide 123

jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 124

Slide 124

Automated jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 125

Slide 125

jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 126

Slide 126

“I need to learn about accessibility and need to write code that conforms with the WCAG 2.1 level A and AA success criteria de ned at https:// www.w3.org/TR/WCAG21/. I want you to be my accessibility coach, a subject-matter expert that makes me think and account for all accessibility requirements and usability enhancements. When you answer questions about accessibility please use reputable sources such as w3.org, webaim.org, developer.mozilla.org, and https:// www.ibm.com/able/. When possible, please provide links and references for additional learning. When you suggest code please use semantic HTML, ensure it is operable using the keyboard, follow WCAG 2.1 su cient techniques, and follow the ARIA Authoring Practices Guide and related design patterns. Do you understand these instructions?” jessbudd@front-end.social jessbudd44 @jessbudd fi ffi jessbudd@bsky.social @jessbudd4

Slide 127

Slide 127

“I need to learn about accessibility and need to write code that conforms with the WCAG 2.1 level A and AA success criteria de ned at https:// www.w3.org/TR/WCAG21/. I want you to be my accessibility coach, a subject-matter expert that makes me think and account for all accessibility requirements and usability enhancements. When you answer questions about accessibility please use reputable sources such as w3.org, webaim.org, developer.mozilla.org, and https:// www.ibm.com/able/. When possible, please provide links and references for additional learning. When you suggest code please use semantic HTML, ensure it is operable using the keyboard, follow WCAG 2.1 su cient techniques, and follow the ARIA Authoring Practices Guide and related design patterns. Do you understand these instructions?” jessbudd@front-end.social jessbudd44 @jessbudd fi ffi jessbudd@bsky.social @jessbudd4

Slide 128

Slide 128

“I need to learn about accessibility and need to write code that conforms with the WCAG 2.1 level A and AA success criteria de ned at https:// www.w3.org/TR/WCAG21/. I want you to be my accessibility coach, a subject-matter expert that makes me think and account for all accessibility requirements and usability enhancements. When you answer questions about accessibility please use reputable sources such as w3.org, webaim.org, developer.mozilla.org, and https:// www.ibm.com/able/. When possible, please provide links and references for additional learning. When you suggest code please use semantic HTML, ensure it is operable using the keyboard, follow WCAG 2.1 su cient techniques, and follow the ARIA Authoring Practices Guide and related design patterns. Do you understand these instructions?” jessbudd@front-end.social jessbudd44 @jessbudd fi ffi jessbudd@bsky.social @jessbudd4

Slide 129

Slide 129

“I need to learn about accessibility and need to write code that conforms with the WCAG 2.1 level A and AA success criteria de ned at https:// www.w3.org/TR/WCAG21/. I want you to be my accessibility coach, a subject-matter expert that makes me think and account for all accessibility requirements and usability enhancements. When you answer questions about accessibility please use reputable sources such as w3.org, webaim.org, developer.mozilla.org, and https:// www.ibm.com/able/. When possible, please provide links and references for additional learning. When you suggest code please use semantic HTML, ensure it is operable using the keyboard, follow WCAG 2.1 su cient techniques, and follow the ARIA Authoring Practices Guide and related design patterns. Do you understand these instructions?” jessbudd@front-end.social jessbudd44 @jessbudd fi ffi jessbudd@bsky.social @jessbudd4

Slide 130

Slide 130

“I need to learn about accessibility and need to write code that conforms with the WCAG 2.1 level A and AA success criteria de ned at https:// www.w3.org/TR/WCAG21/. I want you to be my accessibility coach, a subject-matter expert that makes me think and account for all accessibility requirements and usability enhancements. When you answer questions about accessibility please use reputable sources such as w3.org, webaim.org, developer.mozilla.org, and https:// www.ibm.com/able/. When possible, please provide links and references for additional learning. When you suggest code please use semantic HTML, ensure it is operable using the keyboard, follow WCAG 2.1 su cient techniques, and follow the ARIA Authoring Practices Guide and related design patterns. Do you understand these instructions?” jessbudd@front-end.social jessbudd44 @jessbudd fi ffi jessbudd@bsky.social @jessbudd4

Slide 131

Slide 131

“I need to learn about accessibility and need to write code that conforms with the WCAG 2.1 level A and AA success criteria de ned at https:// www.w3.org/TR/WCAG21/. I want you to be my accessibility coach, a subject-matter expert that makes me think and account for all accessibility requirements and usability enhancements. When you answer questions about accessibility please use reputable sources such as w3.org, webaim.org, developer.mozilla.org, and https:// www.ibm.com/able/. When possible, please provide links and references for additional learning. When you suggest code please use semantic HTML, ensure it is operable using the keyboard, follow WCAG 2.1 su cient techniques, and follow the ARIA Authoring Practices Guide and related design patterns. Do you understand these instructions?” jessbudd@front-end.social jessbudd44 @jessbudd fi ffi jessbudd@bsky.social @jessbudd4

Slide 132

Slide 132

Are you still using the instructions I provided? jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 133

Slide 133

eslint-plugin-jsx-a11y jessbudd@bsky.social jessbudd@front-end.social eslint-plugin-vuejs-accessibility jessbudd44 @jessbudd @jessbudd4

Slide 134

Slide 134

•Images have alt text •Links have accessible content •Mouse events have key events •Labels have “for” attributes •…and more jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 135

Slide 135

react-axe jessbudd@bsky.social jessbudd@front-end.social Vue-axe jessbudd44 @jessbudd @jessbudd4

Slide 136

Slide 136

jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 137

Slide 137

jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 138

Slide 138

jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 139

Slide 139

jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 140

Slide 140

jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 141

Slide 141

Click to edit jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 142

Slide 142

Automated testing is just the first step jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 143

Slide 143

Manual jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 144

Slide 144

jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 145

Slide 145

What to look for Can I see where the focus is? Does the tab order make sense? Can I get to all the components? Can all interactive components be activated? jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 146

Slide 146

Screen readers jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 147

Slide 147

Source: 2021 WebAim screen reader survey #9 VoiceOver JAWS 6.5% 53.7% NVDA 30.7% jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 148

Slide 148

Click to edit

Slide 149

Slide 149

VoiceOver TalkBack jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 150

Slide 150

TalkBack 29% VoiceOver 71% Source: 2021 WebAim screen reader survey #9

Slide 151

Slide 151

What to look for Are all buttons announced correctly? Does link text make sense out of context? Are form labels announced? Announcement of component state jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 152

Slide 152

Summary Using the right HTML Link form labels with inputs Update page titles on routing Manage keyboard focus and make it visible Test your apps jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 153

Slide 153

Final thought… jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 154

Slide 154

The web does not just connect machines, it connects people. - Tim Berners-Lee jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4

Slide 155

Slide 155

resources THANK YOU bit.ly/ndcSydney24 jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4