Aman Explains

Settings

How to create inclusive feedback in SPAs

July 30, 2023• ☕️ 5 min read

When users interact with web applications, they expect immediate feedback for their actions. Providing timely and relevant feedback is crucial to guide users and ensure they understand the application’s behaviour.

In many SPAs, dynamic feedback is primarily designed for sighted users, inadvertently excluding those who rely on screen readers. For e.g, in React, developers may conditionally render an error message when a user’s action triggers an error. While this approach is effective for sighted users, it falls short when it comes to accessibility for users relying on assistive technologies.

In this article, we will utilize a React-based error feedback example to illustrate the issue at hand. Once we identify the problem, we’ll proceed to implement a straightforward solution, ensuring this feedback becomes more inclusive and accessible to all users.


Inaccessible Error feedback

Let’s create a simple login form as shown below. This example will output an error message when the form is submitted with a wrong password.

export default function LoginForm() {
  const [error, setError] = useState(false);

  function handleSubmit(e) {
    e.preventDefault();
    const {
      password: { value },
    } = e.target.elements;
    // Dummy logic of returning error when password mismatches
    if (value !== "test") {
      setError(true);
    } else {
      setError(false);
    }
  }
  return (
    <>
      <form onSubmit={handleSubmit}>
        <label>
          Username: <input type="text" name="username" required />
        </label>
        <label>
          Password: <input type="password" name="password" required />
        </label>
        <button>Log in</button>
      </form>
      {error && (
        <span style={{ color: "red" }}>
          Please check your credentials and try again.
        </span>
      )}
    </>
  );
}

We are conditionally rendering the error based on the boolean value of error state variable. This approach is known as conditionally rendering in React.

You can play with the demo below by typing the wrong password (correct password is test) and pressing the Log in button. It shows an error message when the form is submitted with the wrong credentials. A visually enabled user can easily perceive this message. However, we need to test if visually-impaired users relying on screen reader technology can do the same.

Live Preview

If you are on MacOS, try opening up VoiceOver tool by pressing Command-F5, and try submitting the form with wrong inputs with your eyes closed. How did you go? Did you get any feedback?

Well, an error message does appear on your screen, but unfortunately you can’t see it. It’s not being announced by your screen reader and thus you can’t perceive it. It’s not accessible and you don’t know what went wrong.

Here’s a recorded video of the example above:


The challenge with Screen Readers

In the example above, the error span element wasn’t part of the DOM tree when our LoginForm was rendered the first time. It got injected into the DOM only when the user typed an incorrect password and submitted the form. However, when an HTML element is dynamically added or removed from the DOM, screen readers might not detect these changes. Even though the content is visible on the screen, screen reader users will not be notified about its existence.

Introducing aria-live Attribute

To address the accessibility issue with the error feedback example, we can utilize the aria-live attribute. This attribute is part of the ARIA (Accessible Rich Internet Applications) specification and allows us to designate certain areas of the page as live regions. The value of the aria-live attribute determines how and when changes within that region are announced by the screen reader.

To ensure that screen readers announce errors promptly, we can create a designated live region on the page. When an error occurs, instead of dynamically adding the error message to the DOM, we update the content of this live region. The screen reader will then detect the change and announce the error message to the user. The value of aria-live attributes depends on your use case. Refer to Choosing the aria-live value resource on MDN for more details.

Let’s update our previous example and see how can we implement it.

export default function LoginForm() {
  // --- rest of code ---
  return (
    <>
      <form onSubmit={handleSubmit}>
        <label>
          Username: <input type="text" name="username" required />
        </label>
        <label>
          Password: <input type="password" name="password" required />
        </label>
        <button>Log in</button>
      </form>
      <div
        aria-live="polite"
        aria-atomic="true"
        role="alert"
      >
        {error && (
          <span style={{ color: 'red' }}>
            Please check your credentials and try again.
          </span>
        )}
      </div>
    </>
  );
}

We’ve updated our example by adding a div with the aria-live attribute set to polite. This means that changes within the div will be announced by the screen reader as long as it’s not interrupting any other speech. We’ve also set the aria-atomic attribute to true to ensure that the entire content within the div is announced as a whole.

Also, remember that it’s crucial to include the live region in the DOM right from the beginning, even if it remains initially empty. This ensures that the accessibility tree reader recognizes its existence and can promptly announce any dynamically updated error messages.

Try playing with the updated demo shown below. Notice how the screen reader is now able to announce the generated error. You have made your feedback inclusive to screen reader users too. Well done!

Live Preview

Or you can play the video below to see that in action.


Additional Considerations:

  • Choose the appropriate aria-live value based on the level of importance of the feedback. For critical errors, use assertive to interrupt ongoing speech immediately.
  • Make sure to provide clear and concise error messages to aid all users, not just those with screen readers.
  • Test the application with different screen readers to ensure proper functioning and compatibility.

Conclusion

In this article, we only saw an example of dynamic error feedback, but the concepts of using ARIA regions and providing inclusive feedback can be applied to various types of feedback. Whether it’s success messages, warnings, notifications, or any other interactive response, making them accessible to all users is essential.

this concept is also categorised as one of the inclusive design principles for providing comparable experience.

By incorporating the aria-live attribute for dynamic feedbacks, we can enhance the user experience for individuals who rely on screen readers. Let’s embrace this approach and ensure that all users, regardless of their abilities, can interact seamlessly with our SPA applications.


Amandeep Singh

Written by Amandeep Singh. Developer @  Avarni  Sydney. Tech enthusiast and a pragmatic programmer.