Accessibility assistance (intensive reading of React official document-13)

What is accessibility?

Official description: accessibility (also known as a11y, because it starts with A and ends with Y, with A total of 11 letters in the middle) is A design and creation that can help everyone get services. Accessibility is A necessary condition for assistive technology to correctly interpret web pages.

unscramble

Accessibility assistance refers to a design and creation that can help all people obtain services.

Standards and guidelines

WCAG

Web Content Accessibility Guidelines (WCAG) It provides a guide for the development of accessible websites.

WAI-ARIA

Web Accessibility Initiative - Accessible Rich Internet Applications This file contains the techniques needed to create fully accessible JavaScript widgets.

unscramble

Although most DOM variables and attributes of React are named using hump nomenclature, JSX supports all aria-* HTML attributes in accessibility assistance. Aria - * should use hyphenated nomenclature as it does in HTML.

<input
  type="text"
  aria-label={labelText}
  aria-required="true"
  onChange={onchangeHandler}
  value={inputValue}
  name="name"
/>

Semantic HTML

Official description: semantic html is the basis of barrier free auxiliary function network application. Using multiple HTML elements to enhance the information in your website can usually give you direct access to accessibility assistance.

  • Sometimes semantic HTML will be destroyed by div, ul, ol, table and other elements. At this time, we can use React Fragments to combine various components.
  • give an example
import React, { Fragment } from 'react';

function ListItem({ item }) {
  return (
    <Fragment>
      <dt>{item.term}</dt>
      <dd>{item.description}</dd>
    </Fragment>
  );
}

function Glossary(props) {
  return (
    <dl>
      {props.items.map(item => (
        <ListItem item={item} key={item.id} />
      ))}
    </dl>
  );
}
  • When you do not need to add any prop to the fragment tag and your tool supports it, you can use the following phrase method:
function ListItem({ item }) {
  return (
    <>
      <dt>{item.term}</dt>
      <dd>{item.description}</dd>
    </>
  );
}

Accessibility form

sign

Official description: all HTML form controls, such as < input > and < textarea >, need to be marked to achieve accessibility assistance. We need to provide a screen reader to interpret the annotation.

  • Official reminder: Please note that for should be written as htmlFor in JSX:
<label htmlFor="namedInput">Name:</label>
<input id="namedInput" type="text" name="name"/>

Remind users when an error occurs

Official description: all users should know when an error occurs. The following link tells us how to set an error message for the screen reader:
W3C display user push

Control focus

Make sure your web application works even with a keyboard.

Keyboard focus and focus contour

Official definition: in DOM, the element currently selected to receive keyboard information. We can see the keyboard focus everywhere. It will be surrounded by the focus outline, like the image below.

Skip content mechanism

unscramble

The skip content mechanism is a hidden navigation link that is only visible when navigating using the keyboard. It can be easily implemented by using the internal anchors and some styles of web pages. We can think about the anchor jump of some articles in Github, which probably means that.

Use program management focus

  • Why use programs to manage focus?

Our React application will continuously change the HTML DOM at run time, sometimes this will cause the loss of keyboard focus or be set to unexpected elements. To fix this problem, we need to programmatically focus the keyboard in the right direction. For example, when a pop-up window is closed, reset the keyboard focus to the open button of the pop-up window.

  • Implementation steps
  1. First, create a ref of an element in the JSX of a class component
class CustomTextInput extends React.Component {
  constructor(props) {
    super(props);
    // Create a ref for the textInput DOM element
    this.textInput = React.createRef();
  }
  render() {
  // Use the 'ref' callback function to store the text input DOM element in a variable of the instance
  //(for example, this.textInput).
    return (
      <input
        type="text"
        ref={this.textInput}
      />
    );
  }
}
  1. Focus on this component elsewhere when needed
focus() {
  // Use the original DOM API to explicitly focus on text input
  // Note: we get the DOM node by accessing "current"
  this.textInput.current.focus();
}
  1. Sometimes a parent component needs to focus on an element of its child component. We can pass ref from parent component to child component through props
function CustomTextInput(props) {
  return (
    <div>
      <input ref={props.inputRef} />
    </div>
  );
}

class Parent extends React.Component {
  constructor(props) {
    super(props);
    this.inputElement = React.createRef();
  }
  render() {
    return (
      <CustomTextInput inputRef={this.inputElement} />
    );
  }
}

// Now you can set the focus when needed
this.inputElement.current.focus();

Official tip: Although this is a very important barrier free auxiliary function, it is also a technology that should be used with caution. We should use it to fix keyboard focus when disturbed, rather than trying to predict how users want to use the application.

Mouse and pointer events

Make sure that any function that can be done with the mouse and pointer can also be done only with the keyboard. Relying only on the pointer will cause many situations that make keyboard users unable to use your application.
A typical example of destructive barrier free access caused by click events: external click mode. Users can close open pop-up boxes by clicking outside the element.

  • Method: add a click event on the window object
class OuterClickExample extends React.Component {
  constructor(props) {
    super(props);

    this.state = { isOpen: false };
    this.toggleContainer = React.createRef();

    this.onClickHandler = this.onClickHandler.bind(this);
    this.onClickOutsideHandler = this.onClickOutsideHandler.bind(this);
  }

  componentDidMount() {
    window.addEventListener('click', this.onClickOutsideHandler);
  }

  componentWillUnmount() {
    window.removeEventListener('click', this.onClickOutsideHandler);
  }

  onClickHandler() {
    this.setState(currentState => ({
      isOpen: !currentState.isOpen
    }));
  }

  onClickOutsideHandler(event) {
    if (this.state.isOpen && !this.toggleContainer.current.contains(event.target)) {
      this.setState({ isOpen: false });
    }
  }

  render() {
    return (
      <div ref={this.toggleContainer}>
        <button onClick={this.onClickHandler}>Select an option</button>
        {this.state.isOpen && (
          <ul>
            <li>Option 1</li>
            <li>Option 2</li>
            <li>Option 3</li>
          </ul>
        )}
      </div>
    );
  }
}
  • Problems in the above practice

When using only the keyboard, because the window object will not receive the click event, the user will not be able to switch to the next element using tab. This will prevent users from using some content in your application, resulting in incomplete user experience.

  • Using the correct event triggers, such as onBlur and onFocus, can solve the above problems
class BlurExample extends React.Component {
  constructor(props) {
    super(props);

    this.state = { isOpen: false };
    this.timeOutId = null;

    this.onClickHandler = this.onClickHandler.bind(this);
    this.onBlurHandler = this.onBlurHandler.bind(this);
    this.onFocusHandler = this.onFocusHandler.bind(this);
  }

  onClickHandler() {
    this.setState(currentState => ({
      isOpen: !currentState.isOpen
    }));
  }

  // We use setTimeout to close the pop-up window at the next time point.
  // This is necessary because the loss of focus event will be triggered before the new focus event,
  // We need to confirm a child node of this element through this step
  // Whether it gets the focus.
  onBlurHandler() {
    this.timeOutId = setTimeout(() => {
      this.setState({
        isOpen: false
      });
    });
  }

  // If a child node gains focus, do not close the pop-up window.
  onFocusHandler() {
    clearTimeout(this.timeOutId);
  }

  render() {
    // React transmits the events of losing focus and obtaining focus to the parent node
    // To help us.
    return (
      <div onBlur={this.onBlurHandler}
           onFocus={this.onFocusHandler}>
        <button onClick={this.onClickHandler}
                aria-haspopup="true"
                aria-expanded={this.state.isOpen}>
          Select an option
        </button>
        {this.state.isOpen && (
          <ul>
            <li>Option 1</li>
            <li>Option 2</li>
            <li>Option 3</li>
          </ul>
        )}
      </div>
    );
  }
}
  • Note: aria-* props is officially used to serve screen reader users.

More complex components

A more complex user experience does not mean it is more difficult to access. By programming as close to HTML as possible, accessibility becomes easier, and even the most complex parts can achieve accessibility.

Keywords: React

Added by mcclellanfsu on Mon, 24 Jan 2022 08:00:20 +0200