-
Notifications
You must be signed in to change notification settings - Fork 1.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
When selecting a Menu item, element behind popup receives pointer event #1513
Comments
Double checked, doesn't happen in Safari. Also still happens with using our Buttons |
|
Looked into it more, it does appear that this is the chromium bug I referenced earlier. You are right about FF, honestly don't know what I was doing there, I forgot to turn on touch simulation. The reason that it's not causing an issue with our buttons is that we actually have a line in our code that will ignore the click if it's simulated https://github.com/adobe/react-spectrum/blob/main/packages/@react-aria/interactions/src/utils.ts#L24, but it looks like Firefox is actually plagued by the same bug. I've opened a ticket with them here: https://bugzilla.mozilla.org/show_bug.cgi?id=1692033 As for useLink, I believe that to be that links have their own click event default handler, which we do not prevent https://github.com/adobe/react-spectrum/blob/main/packages/%40react-aria/interactions/src/usePress.ts#L226 and is still the same bugs as above. For reference, here's the minimal reproduction I could think of https://codesandbox.io/s/inspiring-lehmann-i1hjf |
@manelsanz Yes, the bug notes that it happens in FF as well. I would disagree that it's a library issue. You can see the issue happen without our library. I do understand what you're saying though, that this should be something we can help mitigate or work around. Do you have any ideas for solving it? @equinusocio I'm not really sure what you're saying. Are you suggesting a way of fixing it? Are you using pointer events? or what do you use? We've found that there are issues if you try to mix pointer events and mouse events. So we're stuck with using pointer events for this. Some ideas I'd had but haven't had a chance to implement.
|
@equinusocio |
@snowystinger Dunno why by using react-focus-on we don't have that issue. Anyway as you can see from the sandbox, the issue is not related to the responsive mode, since it occurs even with the normal view. |
Possible workaround here. Rember to:
For the record, this is how browsers should behave when users interact using a touch device. Quoting W3C:
I think that in this case, React is failing to preventDefault touch events. One possible workaround is to use the Web API to add an event listener to the interactive element, capture the touch event and prevent the default behavior. This way the compatibility mouse events won´t happen. Here an example of React failing to prevent compatibility events. |
@hernanponcetta thanks for that extra info. Looks like React is both aware of it and not going to do anything about it facebook/react#9809 Interesting, it does appear that you must cancel the touchstart, doing it on pointerdown isn't enough. The issue logged against the browsers has more to do with click being fired on the wrong element because the original target has been removed. So there are two things happening here. I think cancelling the touchstart though is a good direction to try first, it'd render the other issue a moot point if it works for us. I'm not sure how we'd put it on everything though since not everything may use usePress. But maybe it's enough for us to handle it there and in useInteractOutside. That should cover a lot of it. |
Have there been an updates on fixing this? I see there's a PR that is WIP that hasn't been updated since early April. For the record, i see this happening on real phone and tablet devices, not just Chrome's dev tools. |
Hey, we've been trying things, as you can see in the history of the ticket. We've been unable to find a satisfactory workaround to this browser bug thus far and other priorities took us away from looking at it. It could help to chime in on the tickets that were opened against FF and Chrome. We're aware that this happens on real devices as well, unfortunately. We welcome any fresh ideas on how to work around it while we wait for browsers to fix this issue. |
@chrisspadanuta here is an example of the workaround we are using.
Hope that it helps. |
Thanks @hernanponcetta, that workaround is working for us too. |
@hernanponcetta's version works fine but breaks scrolling on the elements. Using this keeps the scroll, but has a performance impact on scrolling (from what I understand, though seemed negligible on faster devices)
|
Another workaround comes from #4027 where you can control the open state of your menu and call close after a slight delay: https://codesandbox.io/s/react-spectrum-menu-pointer-events-forked-w9wxog?file=/src/App.js |
Just want to highlight two edge cases where this breaks normal behavior:
I use something like this:
|
…u in Android Chome due to #1513, Android Chrome would cause a premature focus shift from the resizer input to the body/whatever element was underneath the "resize column" menu option, causing resizing to end early and canceling the 2nd delayed focusInput call. We delay the first focusInput call now so that it happens after the browser delayed click on touch end
…n menu (#4876) * Fix resize input focus issue when triggering resize from dropdown menu in Android Chome due to #1513, Android Chrome would cause a premature focus shift from the resizer input to the body/whatever element was underneath the "resize column" menu option, causing resizing to end early and canceling the 2nd delayed focusInput call. We delay the first focusInput call now so that it happens after the browser delayed click on touch end * clear timeout if it column somehow unmounts before it also reconfirmed that we still need the 400ms timeout for VO iOS
Anyone had any issues with android browsers with this workaround? We got multiple reports from users on some android devices that our buttons stoped working... We can quite consistently reproduce the issue on browserstack, but cannot find a suitable fix for it. Been pulling my hair on it and considered deferring the execution of button click with setTimeout or requestAnimationFrame, but this completely breaks our jest tests (all clicks need runAllTimers to work). Was there any development to find a solution for this issue? It's been open for a long time and it surely is a problem for a lot of users or |
Ran into this issue with a Dialog and a Select (using hooks) and am curious as well. |
I would like to also bring this issue to attention as all usePress interactions are affected by this problem which can be proved by the Demo present in a similar issue. |
Tried both workarounds - the one with useEffect doesn't work for me at all (for some reason the touchend/touchstart event is never triggered), second workaround using setTimeout in onChange event handler seem to fix it only for chrome touch simulator mode. Using real devices (tested on ipad and iphone) in safari causes the pointer events on components beneath it. Further testing with different libraries shows that this must be problem in the library itself because for example radixui can handle popovers just fine. Have you considered using similar approach as them? EDIT: I looked more closely at their select component example and they have similar issue. There are mentioned few approaches that could potentially solve it.
Im not sure if no. 2 cancels something that shouldn't be cancelled |
I can reproduce on iOS 17.2.1 Safari -- having trouble with the dev environment, seems like it's only happening in prod 🤔 Edit: after messing around in chrome, replacing the close button in the modal with a |
took me a while to find the existing issue, but clicking on the modal's close button would trigger the elements underneath it. tried sprinkling some `preventDefault`s on the elements above the button but that didn't work. instead swapping out the usePress powered `<Button` for an ol' fashioned onClick `<button` see: adobe/react-spectrum#1513
took me a while to find the existing issue, but clicking on the modal's close button would trigger the elements underneath it. tried sprinkling some `preventDefault`s on the elements above the button but that didn't work. instead swapping out the usePress powered `<Button` for an ol' fashioned onClick `<button` see: adobe/react-spectrum#1513
I agree with @snowystinger that my issue #5802 is a dupe of this one. My current workaround is the below. Feel free to make me aware of any issues with doing it like this—it seems to avoid the issue for my cases: const { isPressed, buttonProps } = useButton(
{
...useButtonProps,
onPress(e) {
if (e.pointerType === "mouse" || e.pointerType === "keyboard") {
useButtonProps.onPress?.(e);
return;
}
setTimeout(() => {
useButtonProps.onPress?.(e);
}, 1);
},
},
ref,
); I decided to preemptively only allow mouse and keyboard events to be handled "normally", as I'm not sure what other event types have the issue. |
Ran into this issue also, using import { forwardRef, useEffect, useState } from 'react';
import { Modal, ModalOverlayProps } from 'react-aria-components';
export default forwardRef<HTMLDivElement, ModalOverlayProps>(
function CustomModal({ onOpenChange, ...props }, ref) {
const [openSignal, setOpenSignal] = useState<boolean | undefined>();
useEffect(() => {
if (openSignal !== undefined) {
onOpenChange?.(openSignal);
setOpenSignal(undefined);
}
}, [openSignal, onOpenChange]);
return <Modal ref={ref} onOpenChange={setOpenSignal} {...props} />;
}
); |
See adobe/react-spectrum#1513 Change-Id: I1902c7dd0aeff39f081b0317dfe581f280e1f0af GitOrigin-RevId: 0bd6e458aad435eb1a1647691cd2007f56ca91d4
@devongovett Hi. Why is React Spectrum not using native dialog? The API is weird, but can be fixed: https://github.com/evoluhq/evolu.me/blob/main/components/Modal.tsx#L83 Btw, I'm considering moving from React Native for Web to React Aria (since I don't need React Native), but mobile issues hold me back. My question is, do you know RNfW internals? It could be a good source of knowledge. Anyway, thank you for your work. |
Hi there! Are there any updates on this? |
I have a similar issue where I have a EDIT: To clarify, this is with a mouse, not touch. press.mov |
@snowystinger @devongovett is there some way to make It's not just menus, it's any "overlay" type element that disappears when interacted with via bug-encoded.mp4 |
This is one of the biggest problems we are facing right now. We have a HIT testing layer behind that popovers and this issue breaks so many things. |
I've opened a pr to work around this by preventing default on the "touchend" event inside In addition, it looks like the browsers are making progress on a spec change that would fix this: w3c/pointerevents#474. So hopefully in the future we can remove this workaround. |
🐛 Bug Report
When a
Menu
item is selected on a touch device, interactive elements behind the menu popup receive the pointer event as well.🤔 Expected Behavior
Interactive elements behind a menu popup should do nothing when selecting a menu item.
😯 Current Behavior
See this codesandbox for an example with buttons behind a menu popup. When selecting a menu item, the button also gets clicked (and displays the alert).
menu.mp4
Note that this only happens on mobile devices, and when the pointer device simulation is turned on in browser devtools.
💁 Possible Solution
🔦 Context
💻 Code Sample
https://codesandbox.io/s/react-spectrum-menu-pointer-events-wze00?file=/src/App.js
🌍 Your Environment
The text was updated successfully, but these errors were encountered: