react-spectrum
react-spectrum copied to clipboard
DragPreview doesn't work at all with Safari when using a combination of position relative and overflowY auto
🐛 Bug Report
The way DragPreview renders then hide its children for one frame doesn't do the job with Safari. It works with Chrome or Firefox.
🤔 Expected Behavior
The provided DragPreview is rendered in all browsers.
😯 Current Behavior
Nothing, the DragPreview is not visible in the slightest in Safari.
💁 Possible Solution
Unfortunately, after playing with DragPreview, I couldn't find a solution that worked for all browsers. Tried a portal to render behind the app or hiding the preview behind a rectangle that has the same backgroundColor as my app which I tried more for curiosity sake.
If it can't be workaround'ed (after all, Safari is awful), perhaps mention it in the documentation? It's tough to figure it out the hard way after creating the DragPreview.
🔦 Context
Implementing drag & drop with preview in a gridlist component.
🌍 Your Environment
Mac OS 12.3 M1 Pro Safari 15.4 @react-aria/dnd 3.3.0
Drag previews are working for me in Safari 16.5.2 (MacOS Ventura 13.4.1 - Intel), so may be version-specific.
Drag previews are also working for me in Safari 15.6 (MacOS 12.6 - Intel) on this example here
Just upgraded to Safari 16.5.1: It still doesn't work in my fairly complex example in storybook. However, it works in the example link above.
I found the thing that makes it "work" in Safari: just remove any overflowY above the list component. Obviously I can't do that! 😄
Another thing is that my list has position: relative so that I can calculate its items's offsets relative to their list parent. Perhaps I can calculate the offset differently, as a workaround.
You can reproduce it in the GridList example:
By giving the parent (the div right below id="example-21") overflow-y: auto
And the gridlist: position: relative
I'm happy to close this as it's quite niche and it can be worked around, but at least now you're aware of it.
I ran into this same issue and created a minimal repro here: https://codesandbox.io/p/sandbox/mutable-shadow-ml7yq6?file=%2Fsrc%2FApp.js%3A49%2C30 This remains an issue in Safari Version 17.3.1 (19617.2.4.11.12).
For various reasons, I need to use position: relative; overflow: auto; on the parent of ListBox, so i was stuck looking for alternate solutions.
A fix that works for me is to render the custom drag preview in a portal, like this:
renderDragPreview: (items) => {
return <Portal><div>{items[0]["text/plain"]}</div></Portal>
}
Are there any downsides to doing this? If not, should this be the default behavior in react-aria?
same issue:
- on safari desktop 15.6 (I'm late to the party, apparently 17 is there hahah) I get no preview at all
- on chrome mobile v123.0.6312.52, I get a black div of the correct size of the preview
reproduction workflow:
- implement useDrag inside react flow
- and ofc set a preview component to the useDrag hook
@bmcmahen I think react portal is the appropriate solution. It is made for this exact kind of problems. Thank you for the suggestion. I implemented it and it works perfectly on safari desktop. And yes I would also support for this bit to be part of react aria. Note that the portal shouldn't be targeting document.body but a div inside SpectrumProvider
Update: I was able to implement createPortal solution for useDrag hook. But this solution doesn't work for the ListBox component from react-aria-components. indeed createPortal needs to be set as a parent of <DragPreview> and ListBox only allows us to set children of DragPreview
https://github.com/adobe/react-spectrum/blob/8ed86d85f885b8a113fb51b000747839853ec6da/packages/react-aria-components/src/ListBox.tsx#L198
this might be a different issue than what the author posted here tho ? 😆