Skip to content

Latest commit

 

History

History
1670 lines (1023 loc) · 28.1 KB

index.mdx

File metadata and controls

1670 lines (1023 loc) · 28.1 KB

import highlight from '@mdx-deck/themes/syntax-highlighter-prism'

import Slide from "../templates/slide" import ImageSlide from "../templates/image-slide" import CodeBlock from "../components/site-chrome/code-figure" import AccessibleAnimationDemo from "../components/better/animation" import Autocomplete from "../components/better/downshift-autocomplete"

import baseTheme from '../theme' export const themes = [baseTheme, highlight] const openModal = () => { document.querySelector('.modal-curtain').removeAttribute('hidden') } const buttonAction = () => { alert('Button clicked') }

Accessibility in
JavaScript Applications


Who is Marcy Sutton?

Gatsby Sketch note portrait of Marcy by Maggie Appleton A11y Octopus axe Angular

@marcysutton ~ marcysutton.com


Accessibility

Making the web more inclusive
with and for people with disabilities

http://bit.ly/microsoft-inclusive-toolkit


JavaScript Applications

  • Client-rendered: no traditional page reloads
  • Built with frameworks—React, Vue, Ember, Angular, etc.
  • Sometimes server-rendered with “hydration”
  • Challenges and opportunities

What we’ll cover

  • Accessibility debugging
  • Accessibility in JavaScript apps
    • Focus management
    • Client-side routing
    • Announcements
    • Semantic HTML
    • Unobtrusive motion
    • Progressive enhancement
  • Accessibility units
  • Accessible pages
  • Q & A

An app for today

  • Built with Gatsby and React
  • Server and client-rendered
  • Outputs HTML pages by default
  • Includes this slide deck
Gatsby React

Install time

https://github.com/marcysutton/js-a11y-workshop

git clone https://github.com/marcysutton/js-a11y-workshop.git
cd js-a11y-workshop
npm install
npm run develop

View the site locally: http://localhost:8000

Online: https://marcysutton.github.io/js-a11y-workshop


Get some tools


Prototyping with Parcel

Modern development with any JavaScript framework/library

git clone https://github.com/marcysutton/parcel-prototype-scaffold parcel-demo
cd parcel-demo

npm install
npm start

Alternatively: Codepen, Codesandbox, etc.


Which.js?

  • React
  • Ember
  • Angular
  • Polymer
  • Vue
  • Svelte
  • Vanilla

It doesn’t matter.

People just want to use your site

Elmo


Responsive design
is good for accessibility

zoomed-in view of a desktop prototype


#A11y debugging

  • Render in a web browser
  • Test controls with the keyboard
  • Use accessibility web extensions
  • Check color contrast
  • Test with screen readers
  • Use magnification & zoom

Apps to test in the wild

🔍

Debugging in this Gatsby app

Fire up a build in a browser and start testing

$ npm run build
$ npm run serve

http://localhost:9000


Hidden vs. Visible CSS

Demo button
.visually-hidden { 
	border: 0;
	clip: rect(0 0 0 0);
	height: 1px;
	margin: -1px;
	overflow: hidden;
	padding: 0;
	position: absolute;
	width: 1px;
}
.opacity {
	opacity: 0;
}
.displayNone {
	display: none;
}
.visibility {
	visibility: hidden;
}

The accessibility tree

A parallel structure to the DOM

Uses platform Accessibility APIs to communicate page
structure & content to assistive technologies

Chrome accessibility tree dump


Visualize with browser DevTools

Semantic markup and CSS styles impact the accessibility tree

Chrome DevTools accessibility inspector


Focus testing haxx

Paste into browser devTools console

document.body.addEventListener('focusin', (event) => {
    console.log(document.activeElement)
})

Safari, y u no focus?

Safari Preferences


Exercise 1

Test pages with the keyboard

a wooden doll thing repeatedly hitting a keyboard


Exercise 2

Run a browser extension


Exercise 3

Test with accessibility devTools


Testing with Screen Readers

Cheat sheets for getting started


Exercise 4

Screen reader testing

  • OSX Voiceover and Safari
  • NVDA and Firefox Windows
  • JAWS and IE11 or Edge
  • iOS Voiceover and Safari
  • Android Accessibility and Chrome
  • Orca on Linux

Magnification

For users with low vision

  • Browser zoom (all the way: 500%!)
  • OS-level zoom
  • ZoomText & other assistive tech

Exercise 5

Test with magnification

Things to watch out for:

  • Page scrolling
  • Font sizes & scaling
  • UX of interactions when zoomed

Intro to Accessibility
in JavaScript Applications

  • Focus management
  • Live Region announcements
  • Semantic HTML
  • Unobtrusive motion
  • Progressive enhancement

Focus management

Moving the user’s focus as part of an interaction
to alert them to new content

Also: handling focus in disabled and mutated parts of the page


Focus management
building blocks

  • Reachable and operable elements
  • TAB, escape, and arrow keys
  • Visible focus styles
  • Hidden/inert content

tabindex in HTML

Make non-interactive elements focusable

Demo DIV
tabIndex="0"        // in the tab order. see following slides
tabIndex="-1"       // focusable by script, or removes from tab order
tabIndex="99641"    // all up in your tab order. hard to manage
💡 Screen readers go beyond the TAB key

tabindex + role + name

Expose accessibility information for focusable elements.

Demo DIV
<div tabIndex="0"
     role="button"
     aria-label="Close">   
</div>
// focusable
// a button widget, not a DIV
// an accessible name
 

💡 Intended for custom interactive elements, not wrapper DIVs


tabindex + role + name + events

Make custom controls fully interactive

DIV button
<div tabIndex="0"
     role="button"
     aria-label="Close"
     onClick={clickHandler}
     onKeyDown={keydownHandler}>   
</div>
// or just use a button :)
<button aria-label="Close"
        onClick={clickHandler}>   
</button>

ARIA: Accessible
Rich Internet Applications

https://www.w3.org/TR/wai-aria-1.1/

  • role: what is it?
  • state: what's happening to it?
  • property: what's the nature of it?

The first rule of ARIA is don’t use it


Modal layers:
disabling background content

Open curtain
  • aria-hidden="true" and tabindex="-1"
  • inert (+ polyfill)
  • CSS display: none

Focus management
patterns

  • Dropdowns and menus
  • Layers and modals
  • View changes and deletes
  • Loading screens

Widget interactions:
arrow keys or nah?

It depends on the role and pattern

http://w3c.github.io/aria-practices/


Navigation vs. Actions

a.k.a. Links vs. Buttons

Link Button
<a href="/page">Page</a>
<button onClick={action}>Thing</button>

https://marcysutton.com/links-vs-buttons-in-modern-web-applications


Visible focus styles

Useful for so many people and situations, but often turned off for everyone

Demo button
*:focus {
    outline: none;
}
:hover, :focus {
   /* interaction styles here  */
   outline: 5px auto blue;
}

Styling input modalities

Demo button
:focus:not(.focus-visible) {
	outline: 0;
 }
 :focus-visible {
	outline: 3px solid blue;
 }
// in a layout or component
import 'what-input'
/* in your CSS */
[data-whatintent='mouse'] *:focus {
  outline: none;
}

An OS-level preference would be ideal 👍


CSS-in-JS

Cached class names aren't user friendly, e.g. class="sc-bdVaJa"

import React from 'react'
import { styled } from 'styled-components'
const MegaHeader = styled.header`
    background-color: rebeccapurple;
`
const Layout = () => (
    // add a stable CSS class
    <MegaHeader className={`site-wrap`}>
        <h1>My Gatsby Site</h1>
    </MegaHeader>
)

Dropdown Demo

http://localhost:8000/dropdown


Exercise

Create an accessible dropdown


Dropdown answers


Client-side routing

Navigation where JavaScript controls browser history
and dynamically maps URLs to each page or view

Animation of Grommet sorting letters

User testing research on the Gatsby blog


Routing approach

  • A small UI control in each view target, like a skip link
  • Label with nearby content and its action,
    e.g. "Portfolio, skip to navigation"
  • When a user clicks a nav link, move focus to this control

focus diagram


Focus management
patterns: underlying tech


Client-side routing demo

http://localhost:8000


Exercise

Focus on client-side route change


Client-side routing answers


Announcements using
ARIA Live Regions

BBC GIF with a young girl with a megaphone saying attention please


Announcement patterns

Notify assistive tech users without moving focus

  • Asynchronous save / update / etc.
  • Combobox usage / list filtering
  • Chat widgets
  • Title changes*

ARIA Live Regions

Message command centers of varying importance

https://www.w3.org/TR/wai-aria/#live_region_roles

<div role="status"></div>
<div role="alert"></div>
<div aria-live="polite"></div>
<div aria-live="assertive"></div>

Live Region Example


Live Region Gotchas & Tips

  • Include multiple regions for stubborn situations
  • Politeness levels depend on the use case
  • Site-level announcement manager APIs 👍

https://github.com/AlmeroSteyn/react-aria-live


Live region demo

http://localhost:8000/announcer


Exercise

Build a live region


Live region answers


Semantic HTML ✨

  • Use headings & landmarks
  • Start wih native UI controls
  • Build semantics into templates
  • Verify assistive tech output

WebAIM: Semantic Structure


Why semantics are important

Headings save time, and programattic information is useful

Semantic HTML communicates what's on a page to users of assistive technology, reader modes, conversational UIs, search engines, and more


# Semantics IRL

An Event Apart homepage in Chrome DevTools


Tools for testing semantics


Semantics demo

http://localhost:8000/layout


Practice Problem

Use semantic markup

Add markup to a blank page and test it using Accessibility Insights.


Unobtrusive motion

Building safe and delightful interfaces

  • prefers-reduced-motion CSS
  • media, animation playback controls
  • opt-in for autoplay

https://source.opennews.org/articles/motion-sick/


Animation demo

https://codepen.io/marcysutton/pen/yqVVeY


prefers-reduced-motion

@media (prefers-reduced-motion: reduce) {
    .animation {
        animation: none;
        transition: none;
    }
}
var motionQuery = matchMedia('(prefers-reduced-motion)');
function handleReduceMotionChanged() {
  if (motionQuery.matches) {
    /* adjust 'transition' or 'animation' properties */
  } else { 
    /* standard motion */
  }
}
motionQuery.addListener(handleReduceMotionChanged);
handleReduceMotionChanged(); // trigger once on load

WebKit guide ~ MDN docs


reduced-motion demo

http://localhost:8000/animation


Exercise!

Play with reduced-motion and CSS animation or transitions


Reduced-motion answers


Progressive enhancement

Emphasize core web page content first, then add layers of presentation and features on top as browsers/network connections allow

  • Turn off JavaScript
  • Provide accessible baseline markup
  • Add ARIA with scripting
  • Prioritize core user flows

Gatsby & SSR

Output static HTML by default at build time

gatsby build

Gatsby progressive
enhancement demo

http://localhost:8000/enhanced/tablist


Exercise!

Play with progressive enhancement


Progressive enhancement
answers


Testing 🧪

Improving quality in development

  • linting
  • unit tests
  • integration/end-to-end
  • accessibility test APIs
  • continuous integration
  • manual & user testing

Linting

Testing for quality live in a file or on a commit

eslint-plugin-jsx-a11y

  • you might need to reconfigure rules
  • CSS can have an impact
  • rendering makes a difference

Accessibility Units

component-level API concerns

🧩


Unit test approach

  • Test code in isolation
  • Stub inputs/fixture data
  • Often headless
  • Fast changing of state

Accessibility unit tests

  • Component-specific behavior
  • Interaction/focus APIs
  • Text alternatives
  • ARIA states

Article: Writing Automated tests for Accessibility


Unit test demo


Exercise

Write an accessibility unit test!


Unit testing answers


Accessible Pages

interroperability of components

📰


Integration &
end-to-end tests

  • Real-world browser testing
  • Document/page-level rules
  • Widget interrop
  • Color contrast
  • Framework flexibility

const WebDriver = require('selenium-webdriver')
 
describe('Keyboard tests', () => {
    let driver = new selenium.Builder().forBrowser('chrome').build()
        driver.get('http://localhost:4000').then(() => done())

    it('should change state with the keyboard', () => {
      var selector = 'span[role="radio"][aria-labelledby="radiogroup-0-label-0"]';

      driver.findElement(selenium.By.css(selector))
        .then((element) => {
            element.sendKeys(Key.SPACE)
            return element
        })
        .then((element) => element.getAttribute('aria-checked'))
        .then((attr) => {
            expect(attr).toEqual('true')
        })
    })
})

/// <reference types="Cypress" />
describe("Accessibility checks", () => {
  beforeEach(() => {
    cy.visit("/")
    cy.wait(500)
  })
  it("Checks if footer link is focusable and has the correct attributes", () => {
    cy.getAllByText("Gatsby").focus()
    cy.focused()
      .should("have.text", "Gatsby")
      .should("have.attr", "href", "https://www.gatsbyjs.org")
      .should("not.have.css", "outline-width", "0px")
  })
})

No matter what kind of test:
focus on the outcome,
not the code implementation


Using an A11y test API

Rules you don’t have to write


What can we automate?

Tests can catch roughly 30-50% of accessibility issues,
depending on the rule set

👉 Screen readers can’t be automated


Write a combination
of tests to catch a variety
of bugs
💻🔎🐛


Integration test demo

cypress/integration/index.js


Exercise!

Write an end-to-end accessibility test for
keyboard interactions and/or with an accessibility test API


Integration test answers


Continuous Integration

Opportunities to test for accessibility on every commit,
pull request, and deployment

https://marcysutton.github.io/a11y-and-ci/


Track who broke the build

https://twitter.com/zqxwzq/status/868039653697482753

A TV monitor with broken build bandits wanted for bounty


Spoiler: we need to do more

Automated testing and linting only gets us so far.
Projects need manual human testing, too

🙇‍♀️


Manual testing advice

From Eric Bailey

https://www.smashingmagazine.com/2018/09/importance-manual-accessibility-testing/


Accessibility
User Testing

https://inclusivedesign24.org/2019/


Q & A