material-ui icon indicating copy to clipboard operation
material-ui copied to clipboard

VoiceOver Screenreader (blind) user blocked by drawer on iOS (WCAG)

Open petercutting opened this issue 1 year ago • 4 comments

Duplicates

  • [X] I have searched the existing issues

Latest version

  • [X] I have tested the latest version

Steps to reproduce 🕹

Steps:

surf to https://v4.mui.com/components/drawers/ scroll down to Temporary Drawer example start VoiceOver Choose "LEFT" menu (click and then double click). menu appears and rest of screen darkens user is forced to choose a menu option. User cannot close menu by touching dark part of screen

Current behavior 😯

No response

Expected behavior 🤔

user should be able to close the menu in a generic way

Context 🔦

No response

Your environment 🌎

npx @mui/envinfo
  Don't forget to mention which browser you used.
  Output from `npx @mui/envinfo` goes here.

petercutting avatar Oct 12 '22 12:10 petercutting

We haven't been actively working on v4 for over a year. Is it happening with v5 too?

Edit: Ok, I can reproduce on v5, marking this as bug.

mnajdova avatar Oct 14 '22 15:10 mnajdova

i just tested this on mui.com/material-ui/react-drawer + VoiceOver + iOS. my findings:

  • if you tap + double-tap on the backdrop, the drawer closes. this is the expected behavior, because the initial tap moves the reading cursor to the element, and the double-tap activates it. it's the same reason why we tap + double-tap initially to open the drawer.

    • however, this is not easily discoverable by screen reader users, because the backdrop has no accessible name (text content or ARIA-based labelling), which means that it cannot be announced when it receives the initial tap, which in turn means that users have no way of knowing that double-tapping it will perform an action.
  • on macOS, where screen reader users would typically be using a keyboard, the pattern in this component basically boils down to: use Tab to cycle through the focusable elements in the drawer (there's a focus-cycling mechanism), use Escape to dismiss the drawer without selecting an option.

    • however, this doesn't work properly on iOS, where screen reader users typically use swipe gestures to move the reading pointer through the elements in the drawer, and... well, it's kind of complicated and it kinda depends on the settings too, but basically the default behavior is that the reading pointer pulls the focus along, but the focus doesn't pull the reading pointer along. in other words, the focus cycling mechanism as it is currently implemented does not succeed at trapping focus on VoiceOver + iOS, which means that i was able to move focus out of the drawer by simply swiping right a few times, and yet the drawer remained open.

my proposed solutions:

  • bare minimum: detect drawer blur --> close drawer
  • better: detect drawer blur --> close drawer --> programmatically move focus to element that initially opened drawer
  • best: render drawer in the DOM, not at the end of the document, but actually right after the element that initially opened it, so that you can detect drawer blur --> close drawer --> not have to bother moving focus programmatically, because it will naturally flow to the next focusable DOM element

the focus-cycling mechanism can potentially stay or go, depending on what solution is implemented, how it is implemented, etc.

...in theory, at least :D i'm no MUI expert, so we'd have to see how it plays out in practice with the rest of the library :DD

xurxe avatar Oct 17 '22 15:10 xurxe

render drawer in the DOM, not at the end of the document, but actually right after the element that initially opened it, so that you can detect drawer blur --> close drawer --> not have to bother moving focus programmatically, because it will naturally flow to the next focusable DOM element

This can be achieved by passing ModalProps={{ disablePortal: true }} and handling onBlur in the Drawer. See https://codesandbox.io/s/vigorous-goodall-59js6d?file=/demo.tsx:2556-2660 - does it behave better in your opinion?

michaldudak avatar Dec 14 '22 11:12 michaldudak

hmmm apparently doing that creates a different problem. when the portal is disabled, the drawer is rendered inside the <div id="root"> element, which is aria-hidden when the drawer is open, which means that the Drawer itself is also aria-hidden and cannot be interacted with...

xurxe avatar Dec 14 '22 13:12 xurxe

p.s. I believe that https://github.com/mui/material-ui/issues/19450 is related to what I pointed out in my last comment.

xurxe avatar Dec 20 '22 13:12 xurxe