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>
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
.
how can I make the voiceover
read "aria-labelledby" automatically?
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>
)}
</>
);
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.