Search code examples
reactjsaccessibility

the voiceover does not automatically read the "aria-labelledby" contained in my modal when it is displayed on the screen


I am trying to make a modal with accessibility. Basically, the modal gets a child and this child will be the content of the modal:

  <div
    id="modal"
    role="dialog"
    aria-labelledby="modal-label"
    aria-describedby="modal-desc"
    tabIndex={0}
    className="modal"
  >

    {*/  {children} */}

   <div className="flexContainer">
    <div id="modal-desc">
      <div>hey</div>
      <div>
        <div>This is the description</div>
        <div>I am a button</div>
      </div>
    </div>
    <div>
      <div id="modal-label">This is the title</div>
    </div>
   </div>
  </div>

enter image description here

When the modal opens, the voiceover reads the texts as it is in the gif, but I don't know why it doesn't read the aria-labelledby. My idea is that I can pass any child to my modal and the voiceover reads everything that is contained in aria-labelledby and in aria-describedby.

enter image description here

how can I make the voiceover read "aria-labelledby" automatically?

this is my live code

const [openModal, setOpenModal] = useState(false);

const Modal = ({ children }) => {
useEffect(() => {
  document.querySelector("#modal")?.focus();
}, []);

return (
  <div
    id="modal"
    role="dialog"
    aria-labelledby="modal-label"
    aria-describedby="modal-desc"
    tabIndex={0}
    className="modal"
  >
    {children}
  </div>
);
};

const ModalContent = () => {
return (
  <div className="flexContainer">
    <div id="modal-desc">
      <div>hey</div>
      <div>
        <div>This is the description</div>
        <div>I am a button</div>
      </div>
    </div>
    <div>
      <div id="modal-label">This is the title</div>
    </div>
  </div>
);
};

return (
<>
  <button
    aria-hidden="true"
    onClick={() => {
      setOpenModal(true);
    }}
  >
    open modal
  </button>
  {openModal && (
    <Modal>
      <ModalContent />
    </Modal>
  )}
</>
);

Solution

  • There's nothing wrong with the way you're using aria-labelledby, however it may be that the content of your modal (#modal-desc) is being added after the modal container (#modal), so the #modal-label ID is not immediately available in the DOM when the modal first appears. Sometimes this can cause problems for screen readers when content (particularly content that is linked to aria-labelledby or aria-describedby) is added dynamically to the DOM.

    A better way to ensure that your modal label is announced is to include it in the aria-label attribute in your dialog container, e.g.:

    <div id="modal" role="dialog" aria-label="This is the title" aria-describedby="modal-desc" tabIndex="0" class="modal">
    
    

    As an aside, you have aria-hidden="true" on your "open modal" button. You should remove this because it hides the button from screen readers.