reactour icon indicating copy to clipboard operation
reactour copied to clipboard

Accessibility of popover

Open brennanyoung opened this issue 1 year ago • 0 comments

Please address the accessibility of popover, which has a number of issues.

Focus is not moved to the popover when it opens, and, for the modal version (where everything "behind" is greyed out) the tab sequence is allowed to wander around the greyed-out background content. That's not good.

Ideally you should use the HTML5 <dialog> element. whose spec and implementations finally stabilized in 2022. This takes care of a lot of the tricky stuff. This means that role="dialog" will no longer be necessary. More details at the following links. https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dialog https://www.scottohara.me/blog/2023/01/26/use-the-dialog-element.html

The inert attribute also works well (to prevent the tab sequence from wandering into the greyed-out background content). https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/inert

If you use dialog.openModal() rather than dialog.open() you get the inert behavior 'for free'.

For non-modal popovers, it may be smart to use an aria relationship attribute to associate the element with the popover. The most obvious candidate is aria-details. When the popover is closed, this attribute should be removed.

Important notes:

Consider what should get focus when the dialog opens. There are different opinions about what is most correct. Candidates are:

  • focus() the dialog itself
  • focus() the first heading in the dialog (the heading requires a negative tabindex)
  • focus() the first operable element (button, link etc.) inside the dialog

I imagine that different content authors will have different intentions about this, so ideally, reactour should permit any one of these, perhaps defaulting to the first one (focus the dialog).

Test to make sure that tab focus is constrained to the popover when it is open. If you can tab to stuff in the background, it's broken.

Listen for ESC keypress while popover is open. This should close the popover.

It is common practice to provide a close button for most dialogs. Perhaps reactour could allow a reference to this button to be passed via the popover config object?

Non-operable content (headings, paragraphs) inside a modal might require a div wrapper with role="document", especially on Safari, otherwise the screen reader might be unable to reach that content. This may be a legacy problem with Safari's ARIA implementation, and might no longer be a problem with a proper HTML5 <dialog>. Worth testing on Mac and iOS.

When a dialog closes, the most common practice is to focus() on the thing that opened it. In the case of popover, I dare say that we'd want to focus() on the element currently 'highlighted' by the popover. (Discuss?)

brennanyoung avatar Apr 17 '23 12:04 brennanyoung