Page MenuHomePhabricator

[Spike] Determine best approach for making Dialog accessible to keyboard and screenreaders
Closed, ResolvedPublic3 Estimated Story Points

Description

Issue

When the dialog is first opened, the focus is not set in a place that makes it easy to access the content in the rest of the dialog, and it's possible to navigate components hidden behind the dialog.

Resources

https://www.w3.org/WAI/ARIA/apg/patterns/dialog-modal/

Developer notes

While aria-modal="true" removes requirement of putting aria-hidden on background content, as the aria-modal informs assistive technologies that content outside a dialog is inert, it's the safer way currently to have both attributes in use on the dialog and the background content elements.

The escaping of dialogs by pressing (ESC) has already been part since the original Dialog implementation.

Best practices identified

  • Add aria-modal="true" to the role="dialog" element.
  • Focus on initial dialog open should work in a predictable way.
  • Users should not be able to interact with content behind the dialog when open.
    • Remain aria-hidden="true" for its wider support than only aria-modal on background elements incl script
    • Add inert as future-facing attribute for non-interactable background elements as well
  • The user should always have a way to exit the dialog using keyboard navigation. In initial implementation

Event Timeline

CCiufo-WMF set the point value for this task to 3.Jul 20 2023, 8:46 PM
CCiufo-WMF moved this task from Needs Refinement to Up Next on the Design-System-Team board.

Out of the acceptance criteria listed above, I think the most involved will be:

  • Focus on initial dialog open should work in a predictable way.
  • Users should not be able to interact with content behind the dialog when open.

In VoiceOver, I'm currently able to move focus behind the dialog backdrop while it is open. In non-screenreader-usage this is something we are already preventing, but it looks like we'll need to re-work our current "focus trap" implementation to provide a better experience for users of assistive technology.

  • Add aria-modal="true" to the role="dialog" element

This should be straightforward to do.

  • The user should always have a way to exit the dialog using keyboard navigation.

This is already the case – I have no issues exiting the Dialog in VoiceOver or in the Chrome Screenreader extension.

In terms of improving focus handling and keyboard navigation, I think we should remove the dedicated DOM elements for focusTrapStart, focusTrapEnd, and focusHolder in favor of handling the focus event (this is what the APG examples do). However, I do wonder how we should handle situations where no focusable content exists in the dialog (and no button is used). The dialog is very configurable, so it's possible for someone to set one up where there is no visible button and no focusable content. I'm not sure what we want to do in that case in terms of programmatic focus for users of assistive tech.

Volker_E renamed this task from [Spike] Determine best approach for making Dialog accessible to keyboard and VO to [Spike] Determine best approach for making Dialog accessible to keyboard and screenreaders.Aug 10 2023, 2:47 PM

In terms of improving focus handling and keyboard navigation, I think we should remove the dedicated DOM elements for focusTrapStart, focusTrapEnd, and focusHolder in favor of handling the focus event (this is what the APG examples do). However, I do wonder how we should handle situations where no focusable content exists in the dialog (and no button is used). The dialog is very configurable, so it's possible for someone to set one up where there is no visible button and no focusable content. I'm not sure what we want to do in that case in terms of programmatic focus for users of assistive tech.

This seems to prepare for intended corruption of usability by a malicious library application. How would a dialog be intended to be escapable by <ESC> but feature no GUI focusable element like an OK button or an X in the corner at all?

Change 947971 had a related patch set uploaded (by VolkerE; author: VolkerE):

[design/codex@main] [WIP] Dialog: Add `aria-modal="true"`

https://gerrit.wikimedia.org/r/947971

We should consider applying inert (MDN docs, caniuse) attribute additionally to the focus trap.
Note, that OOUI has implemented inert in v0.44.1 (by @Esanders).
A few other notes from the best practices following implementation. Adding aria-hidden to all non-Dialog, incl parent dialogs, elements on page.

And keeping the focus trap mechanism as is (research by @matmarex)

I found a few articles that clearly recommend trapping the focus in the dialog (and not just preventing it from moving to the rest of the page):
https://www.w3.org/TR/wai-aria-practices-1.1/examples/dialog-modal/dialog.html#kbd_label
https://allyjs.io/tutorials/accessible-dialog.html#reacting-to-kbdtabkbd-and-kbdshift-tabkbd
https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/dialog_role#focus_management

Volker_E updated the task description. (Show Details)

From our discussion on importance of dialog at body bottom in today's eng enclave: Beyond possible focus quirks without the teleported position, another mention on the ARIA APG docs is also worthwhile taking into account:

The dialog element is not a descendant of any element that has aria-hidden set to true.

So putting the dialog end of body in DOM instead of as child element inside a triggering element containing div is preventing a possible accessibility blocker authoring mistake: where a dev has put aria-hidden on some parent element of the dialog itself.