WordPress / gutenberg

The Block Editor project for WordPress and beyond. Plugin is available from the official repository.
https://wordpress.org/gutenberg/
Other
10.34k stars 4.13k forks source link

iOS VoiceOver unable to dismiss bottom sheet that has overflowing content #29358

Open dcalhoun opened 3 years ago

dcalhoun commented 3 years ago

Description

After opening a bottom sheet that has enough content within it to extend past the max height for a bottom sheet, it is impossible to dismiss/close the bottom sheet using the iOS VoiceOver accessibility feature.

The inability to close the bottom sheet with VoiceOver does not occur if the bottom sheet contents are short enough to not trigger overflow scrolling in the bottom sheet.

This issue does not appear to occur for Android's TalkBack.

Step-by-step reproduction instructions

  1. Open a post on the iOS app.
  2. Add a Cover block with an image set as the background.
  3. Publish the post and open it again.
  4. Enable VoiceOver.
  5. Open the Cover block inspector bottom sheet by tapping the settings button no the block.
  6. Tap the overlay above the bottom sheet content.
  7. Double tap the overlay above the bottom sheet content.

Expected behaviour

The bottom sheet closes.

Actual behaviour

The bottom sheet remains open.

Screenshots or screen recording (optional)

https://user-images.githubusercontent.com/438664/109229307-b91ee780-7788-11eb-89da-450e07d20d37.mov

WordPress information

Device information

hypest commented 3 years ago

Added the "Priority High" label as this is blocking the typical use of a major block under a11y flows!

guarani commented 3 years ago

Hi @dcalhoun, I gave this a look and couldn't reproduce the issue unfortunately. I made a similar post to the one shared in the video above, opened the Cover block settings (it had inner scroll) and was able to close it using VoiceOver by double tapping on overlay area above the bottom sheet.

Here's a narrated video of me doing this:

https://user-images.githubusercontent.com/1898325/110362378-f94f5700-801f-11eb-8ecd-c1f6594c526d.mov

Is there any other info that could help me reproduce this?

dcalhoun commented 3 years ago

@guarani that is unfortunate. I am able to reproduce the issue just now with two separate iOS devices.

Using an unpublished post with a Heading block and fixed-background Cover block, just like the one in your video, the issue occurs following the steps outlined in my original comment. 😕

Maybe the next best step is to see if anyone else on is able to reproduce on their own device?

guarani commented 3 years ago

Thanks for double-checking, @dcalhoun! I'm on an iPhone 11, iOS 14.4, WPiOS 16.8 so there doesn't seem to be much difference there.

I wonder if we're using VoiceOver in the same way (I'm not an expert!). Here's something I noticed now: If I open the bottom sheet I can close it with a double tap on the overlay – only if I haven't focused any element inside the bottom sheet, otherwise (i.e. if I've selected with VoiceOver something inside the bottom sheet) I need to tap once outside the bottom sheet and then double tap closes it.

Not sure if that changes anything – but thought I'd mention.

dcalhoun commented 3 years ago

If I open the bottom sheet I can close it with a double tap on the overlay – only if I haven't focused any element inside the bottom sheet, otherwise (i.e. if I've selected with VoiceOver something inside the bottom sheet) I need to tap once outside the bottom sheet and then double tap closes it.

@guarani that makes sense as VoiceOver's double tap triggers a "tap" on the current selected element. In your described first flow the selection remains on the overlay, so double taping triggers as "tap" which dismisses it. If you move selection to a child of the bottom sheet, double tapping would trigger a "tap" on the newly selected child.

I'm a bit puzzled by the different outcomes we are seeing currently.

guarani commented 3 years ago

After syncing up with @dcalhoun, we realized that the trick to reproducing this bug was to use a published WPiOS post (I've updated the steps to reproduce above).

It's worth noting here that in my testing the VoiceOver "two-finger scrub" z-gesture does work to close this bottom sheet in all scenarios. So users familiar with the z-gesture might not be affected by this bug.

Looking at the iOS system bottom action sheet to see which VoiceOver commands work with it, I only saw two ways to close it: a) the z-gesture, or b) by putting focus on the Cancel button and double tapping. Notably, I could not put focus outside it and double-tap to close using VoiceOver as I expected. You can try in the Gutenberg demo app by trying to dismiss the action sheet that is presented when you tap the ellipsis button.

While it's still an issue though that VoiceOver users can close the bottom sheet using a double-tap on unpublished posts, that's a WPiOS issue, not a Gutenberg issue. So I then tried to reproduce the bug in the Gutenberg demo app and managed with a contrived example.

How to reproduce in the Gutenberg demo app

Replace the contents of packages/edit-post/src/editor.native.js with the following:

See code:
    import { Component } from '@wordpress/element';
    import { View, Button, Text } from 'react-native';
    import { BottomSheet } from '@wordpress/components';

    class Editor extends Component {
        constructor() {
            super( ...arguments );
            this.state = { isVisible: false };
        }

        render() {
            return (
                
                    

I did some more digging into the react-native-modal library (which powers <BottomSheet>) and is powered by RN's standard <Modal> component. My aim was to check a few things:

  1. If newer versions of the library have the same issue (we're currently on 6.5.0 and while there are many newer versions, some might depend on a higher RN version).
  2. If the issue lies in the <BottomSheet> component itself, which is quite complex and does a few tricks such as switch between a <ScrollView> and a <View> depending on the height of its contents.

I made some progress but not enough to share at the moment. I'll loop back here when I get the chance.

dcalhoun commented 3 years ago

Looking at the iOS system bottom action sheet to see which VoiceOver commands work with it, I only saw two ways to close it: a) the z-gesture, or b) by putting focus on the Cancel button and double tapping. Notably, I could not put focus outside it and double-tap to close using VoiceOver as I expected. You can try in the Gutenberg demo app by trying to dismiss the action sheet that is presented when you tap the ellipsis button.

Interesting. It does appear that native Action Sheets cannot be dismissed via VoiceOver by tapping the overlay. However, one can dismiss an Activity View via VoiceOver by tapping the overlay. I might argue our Bottom Sheet is more like the latter and therefore should support dismissal by tapping the overlay.

While it's still an issue though that VoiceOver users can close the bottom sheet using a double-tap on unpublished posts, that's a WPiOS issue, not a Gutenberg issue.

I'm not sure I follow this statement. Are you stating the issue is that you can or cannot dismiss the Bottom Sheet? Why does it not relate to Gutenberg?

If the issue lies in the <BottomSheet> component itself, which is quite complex and does a few tricks such as switch between a <ScrollView> and a <View> depending on the height of its contents.

Removing as many variables as possible is a good call. In my original exploration, I was able to reproduce the issue after removing all children by merely forcing the height of the Bottom Sheet to be more than the max height for the container. Something odd is occurring with the overflow scrolling.

guarani commented 3 years ago

I haven't looked at this since the week before last, but this is still in my to-do list.

Interesting. It does appear that native Action Sheets cannot be dismissed via VoiceOver by tapping the overlay. However, one can dismiss an Activity View via VoiceOver by tapping the overlay. I might argue our Bottom Sheet is more like the latter and therefore should support dismissal by tapping the overlay.

I definitely agree our Bottom Sheet should support dismissal by tapping on the overlay. The fact that it does work when the Bottom Sheet has no scroll is enough to suggest that it should continue to work when there is scroll.

While it's still an issue though that VoiceOver users can close the bottom sheet using a double-tap on unpublished posts, that's a WPiOS issue, not a Gutenberg issue.

I'm not sure I follow this statement. Are you stating the issue is that you can or cannot dismiss the Bottom Sheet? Why does it not relate to Gutenberg?

Sorry for the confusion. I meant to say that while it's still an issue that VoiceOver users cannot close the bottom sheet using a double tap on published posts (I negated all the things 🤦), that appeared to point to a WPiOS issue. Anyhow, I was then able to reproduce in Gutenberg, so this ended up being a Gutenberg issue as well.

Removing as many variables as possible is a good call. In my original exploration, I was able to reproduce the issue after removing all children by merely forcing the height of the Bottom Sheet to be more than the max height for the container. Something odd is occurring with the overflow scrolling.

Yep, this will need a bit more digging. I'll leave myself as the assignee since this is still on my plate.

guarani commented 2 years ago

Removing myself as assignee since I haven't gotten to it in a number of months. Since this is high priority, @mchowning, do you think this can be left unassigned or should I or someone else pick it up?

mchowning commented 2 years ago

Thanks for removing your assignment @guarani . No one else is available to work on this right now, so I'll leave it unassigned, but leave it as high-priority.

dcalhoun commented 2 years ago

I have not found a solution to this, but spent time researching this and wanted to capture my findings.

It would appear this may be related to the pointerEvents="box-none" attribute, and a potential bug in its implementation.

The Gutenberg project leverages react-native-modal for the bottom sheet. react-native-modal includes an absolutely-positioned backdrop that supports dismissing the modal on tap. react-native-modal leverages pointerEvents="box-none" on the sibling content container to ensure touch events "pass through" the content container and arrive at the backdrop, provided the tap is not atop a content container child.

The "pass through" of touch events appears to work when VoiceOver is disabled or the modal content container is relatively short (e.g. less than 30% of the screen height). However, with a taller content container, it is not possible to activate the backdrop's onPress callback using VoiceOver.

I have opened https://github.com/facebook/react-native/issues/32759 in hopes of receiving guidance from the React Native community on this issue. I plan to remove myself as the assignee until there is some activity on the newly created React Native issue.

SiobhyB commented 9 months ago

I'm removing the priority label as part of our recent effort to re-evaluate [Priority] High issues. I feel torn removing the priority for an accessibility issue, but my thinking is as follows:

I think a fix would still be valuable, but don't think it's correct to communicate that this is a high priority task for our team. I'm open to different thoughts, though!