CodeBlanks Logo Icon CodeBlanks

Challenge: Accessible modal

Write a fully accessible modal with ARIA, keyboard and portal.

Challenge: Accessible modal

In this challenge you will write an accessible modal. The modal root carries role="dialog" and aria-modal="true". You move focus inside with useRef.

The close button is labelled with aria-label. The Esc key closes the modal; you add a keydown listener inside useEffect. While the modal is open focus stays inside; Tab does not leave it.

Practice Write the AccessibleModal component

Write AccessibleModal. Use useRef(null) and call ref.current.focus() in a useEffect. The root should be <div role="dialog" aria-modal="true" tabIndex="-1" ref={ref}> containing <button aria-label="Close" onClick={onClose}>X</button>. Take an onClose prop. Export it.

Starter code

App.jsx
import { useRef, useEffect } from 'react';

// Write the AccessibleModal component here

Sample solution

App.jsx
import { useRef, useEffect } from 'react';

function AccessibleModal({ onClose }) {
  const ref = useRef(null);
  useEffect(() => {
    ref.current.focus();
  }, []);
  return (
    <div role="dialog" aria-modal="true" tabIndex="-1" ref={ref}>
      <button aria-label="Close" onClick={onClose}>X</button>
    </div>
  );
}
export default AccessibleModal;

Questions and answers

Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.

1 What should the Esc key do in an accessible modal?

  • Submit the form
  • Reload the page
  • Nothing
  • Close the modal Correct answer

Explanation: answer: Esc should close the modal.

2 Fill in the blank: label the close button

Question
<button ____="Close" onClick={onClose}>X</button>
Answer
<button aria-label="Close" onClick={onClose}>X</button>

Explanation: aria-label gives the button an accessible label.

All lessons in Advanced