Log of QDelft

React Accessibility Patterns


  • Almero Steyn
  • QDelft B.V.
  • almerosteyn.com
  • twitter.com/kryptos_rsa

React

React logo
"A JavaScript library for building user interfaces." - React docs

Who uses React?

Facebook logo Netflix logo Airbnb logo Instagram logo Whatsapp logo Tenon logo Wehkamp logo BBC logo

How accessible are they?

Movie poster of The Good, the Bad and the Ugly

The Good-a11y

The Good from the movie the Good, the Bad and the Ugly
Image capture and Axe scan of tenon.io
Image capture and Axe scan of airbnb

The other two

The Good from the movie the Good, the Bad and the Ugly The Good from the movie the Good, the Bad and the Ugly
Image capture and Axe scan of wehkamp
Image capture and Axe scan of docker

But why?

Cat confused about the accessible state of React websites
Image of Harry Potter turning a div into a button

        <div className="looks-like-a-button"
             onClick={this.onClickHandler}>
               Press me please
        </div>
    

There has to be a better way?

Confusion about how bad the web is

Example application

https://github.com/AlmeroSteyn/react-a11y-patterns

React component tree

Depicts the React virtual DOM and how it relates to the real DOM

React component class


import React, { Component } from 'react';

class Demo extends Component {
    render() {
        return (
            {this.props.displayText}
        );
    }
}

export default Demo;

React component function


import React from 'react';

const Demo = ({ displayText }) => (
    {displayText}
);

export default Demo;

Using a component


import React from 'react';
import Demo from './Demo';

const Root = () => (
     <Demo displayText="Show this text"/>
);

export default Root;

React virtual DOM + Reconciler

Depicts the React virtual DOM and how it relates to the real DOM

React virtual DOM in browser

A debug view of the React DOM in React dev tools

React actual DOM in browser

A debug view of the DOM to compare to that of the React DOM of the previous slide

JSX

HTML-like syntactic JavaScript sugar.


        <label htmlFor={nameId}>{nameLabelText}</label>
        <input id={nameId} type="text" />
    
Renders to HTML in the DOM.

         
         
    

Good HTML makes good JSX


const AppNavigation = () =>
  ;

First rule of ARIA

Bad idea:


       <div className="looks-like-button"
            onClick={this.onClickHandler}>
         Press me
       </div>
     

Good idea:


         <button onClick={this.onClickHandler}>
            Press
         </button>
     

Intact header symantics

Diagram of HTML headers

const HeaderWithLevel = ({ headerText, level }) => {
  const HeaderLevel = `h${level}`;
  return <HeaderLevel>{headerText}</HeaderLevel>;
};

Components and unique id's


 import uuid from 'uuid';
 //...
 this.inputId = uuid.v4();
 //...
 render() {
    //...
    <label htmlFor={this.inputId}>
      {labelText}
    </label>
    <input id={this.inputId}
      onChange={this.onChangeHandler}
      value={value}
    />
    //...
 }
 
https://github.com/kelektiv/node-uuid

Routing is a11y silent


const AppMain = () =>
  
<Switch> <Route path="/todos" component={Todos} /> <Route path="/todo" component={Todo} /> <Route path="/contact" component={Contact} /> <Redirect to="/todos" /> </Switch>
;

Set focus after navigation


class PageFocusSection extends Component {
  componentDidMount() {
    this.header.focus();
  }
  render() {
    const { children, headingText } = this.props;
    return (<section>
        <h2 tabIndex="-1" ref={header => (this.header = header)}>
          {headingText}
        </h2>
        {children}
      </section>);
  }
}

Changing the document title


//...
import DocumentTitle from 'react-document-title';
//...
const SetDocTitle = ({ docTitle, children }) =>
  <DocumentTitle title={docTitle}>
    {children}
  </DocumentTitle>;
https://github.com/gaearon/react-document-title

ARIA live announcer


//...
import { LiveAnnouncer, LiveMessage } from 'react-aria-live';
//...
render() {
return (
  <LiveAnnouncer>
    <LiveMessage message={this.state.a11yMessage}
                 aria-live="polite" />
    {this.props.children}
  </LiveAnnouncer>
);
}
//..
https://github.com/AlmeroSteyn/react-aria-live

React a11y docs

Screenshot of the React accessibility docs

Questions


Presentation online at:

http://almerosteyn.com/slides/
  • Almero Steyn
  • QDelft B.V.
  • almerosteyn.com
  • twitter.com/kryptos_rsa