adobe / react-spectrum

A collection of libraries and tools that help you build adaptive, accessible, and robust user experiences.
https://react-spectrum.adobe.com
Apache License 2.0
12.8k stars 1.1k forks source link

React Aria: Replace Esc key listeners with a CloseWatcher in supported browsers #5531

Open philwolstenholme opened 10 months ago

philwolstenholme commented 10 months ago

Provide a general summary of the feature here

Chrome 120 introduced the concept of a CloseWatcher that can replace a Esc key listener. A CloseWatcher fires when the Esc key is pressed but has the bonus of being triggered by 'back' gestures or buttons on Android, 'back' physical buttons on gamepads, and potentially in the future other 'close' gestures like iOS VoiceOver's two-finger scrub "z" gesture.

Multiple CloseWatchers can be created and will stack, and a user gesture will trigger the watcher at the top of the stack (removing it from the stack).

From the WICG explainer:

Currently, web developers have no good way to handle these close requests. This is especially problematic on Android devices, where the back button is the traditional close request. Imagine a user filling in a twenty-field form, with the last item being a custom date picker modal. The user might click the back button hoping to close the date picker, like they would in a native app. But instead, the back button navigates the web page's history tree, likely closing the whole form and losing the filled information. But the problem of how to handle close requests extends across all operating systems; implementing a good experience for users of different browsers, platforms, and accessibility technologies requires a lot of user agent sniffing today.

Is this something that React Aria would be interested in using instead of an Esc key listener (in supported browsers) in useOverlay? We could fall back to the key listener in browser that don't support new CloseWatcher(). I'd be happy to try raising a PR.

๐Ÿค” Expected Behavior?

We will get the benefits of the CloseWatcher and mobile users will be less likely to suffer data loss or irritation if they use a back gesture that is uncaught and they end up on a different page as a result.

๐Ÿ˜ฏ Current Behavior

Currently we only dismiss overlays when the Esc key is pressed.

๐Ÿ’ Possible Solution

See general summary โ€“ I would be happy to try adding this via a PR

๐Ÿ’ป Examples

๐Ÿงข Your Company/Team

External to Adobe (my team is working on a rebuild of http://shop.coop.co.uk for Co-op in the UK)

bramus commented 10 months ago

For completeness: the linked to https://close-watcher-demo.glitch.me/ demo comes with a polyfill.

LFDanLu commented 10 months ago

I think this would be a good update, especially if it gets support for screen readers as you alluded to. Currently we rely on visually hidden dismiss buttons to allow screen reader users to close some of our overlays, but navigating to those in a large list can be problematic. Having built in gesture support to trigger those overlay closes would solve that for us. I'll bring this up to the team to field opinions.

LFDanLu commented 10 months ago

Talked to the team and we are definitely interested in this, but we'd like to get some research done on how the device back buttons on devices work with native elements so we know which ESC key handlers to replace with CloseWatcher (for example overlays seems like a good place but we wouldn't want to replace the ESC key for something like our TableColumnResizer). Let us know if you'd like to help out with this research!

lukewarlow commented 10 months ago

The native html dialog (when modal) and popovers both have the close watcher behaviour. So basically any elements that use escape to "close" (selects, modals, tooltips etc) are prime candidates for a close watcher.

Looking through react aria that would seem to be:

Pickers - Select, Combobox Overlays - Modal, Popover, Tooltip

Changing the above components should address the use cases for the derivatives such as Date picker which should also have this.