dnd-kit icon indicating copy to clipboard operation
dnd-kit copied to clipboard

Window resize events interrupt iOS 15 Safari dragging.

Open adriantrunzo opened this issue 2 years ago • 6 comments

Hi 👋 ,

This issue was tricky to track down, so I hope that my explanation here is clear!

The Problem

On iOS 15, Safari hides and shows the browsing tools (location bar, back button, bookmark button, etc) when the page is scrolled up or down, respectively. Showing and hiding the browsing tools appropriately triggers a window resize event. That resize event causes the dragging operation to be cancelled. Before I learned that the resize event was being fired and found that line of code, the behavior was unexpected and seemed very odd, because if the screen had been scrolled just right and I wasn't dragging over a large distance, I didn't notice the issue.

The issue is not present on iOS 14 and earlier.

How to Reproduce

Here's a codesandbox that exhibits the issue: https://codesandbox.io/s/resize-interrupts-ios-15-dnd-kit-wp5d8k. This example is a simple adaptation of the Sortable Stories and very similar to the code in the private repository where I encountered the issue.

Note that how you view the example makes a difference (beyond the fact that you must be on iOS 15). This difference also explains why this behavior is not visible in the Stories.

If you are viewing the example in the default codesandbox view, with the codesandbox interface elements, you will not see the issue. The reason is that the page is not scrollable, just the content section where the dnd-kit elements are. In other words, the HTML body (or root element) has styling like overflow: hidden; height: 100vh; width: 100vw; and never scrolls. Notice how the Safari location bar never disappears:

https://user-images.githubusercontent.com/1218900/160944223-0091f2bf-d3b9-4b40-a18d-cb452e0a9a88.mov

If you then view the example in a new window, without the codesandbox interface elements, you will encounter the issue. Now the page can scroll and the browser default behavior of showing and hiding the browsing tools comes into effect:

https://user-images.githubusercontent.com/1218900/160944477-cae01126-b2bd-4555-a6f9-5d864637f1a9.mov

Discussion

I am sure there is a good reason to cancel the drag on window resize in some cases, but as shown above it leads to unexpected behavior on iOS 15. One workaround is to update our app to make the page not scrollable using styling like that above. However, that workaround requires a change that affects the entire app and we'd have to accept that the location bar will always be taking up vertical space in our mobile view.

Is the cancel-on-resize handler currently in AbstractPointerSensor needed in all cases? Perhaps the drag operation doesn't need to be cancelled if the resize is only vertical?

If there is no reasonable, short-term solution to this issue, I suggest updating the documentation to outline that the drag-and-drop elements must be within a page that does not scroll on mobile. An inner container that contains those elements is the one that should scroll.

Thanks for reading and for sharing this great library!

adriantrunzo avatar Mar 30 '22 23:03 adriantrunzo

Hey @adriantrunzo,

Thanks for the detailed report. Originally the idea behind canceling dragging on window resize was to get around some limitations with @dnd-kit at the time.

There's still a couple of limitations at the moment that would prevent this from working well even if you removed the cancel on resize handler in AbstractPointerSensor, but we should definitely fix this.

It's not acceptable that @dnd-kit no longer works on iOS 15 Safari, so this is definitely going to be high priority to fix.

The main thing that needs to be done for this to work properly is to update the measurements of the scrollable ancestor bounding rectangles when they resize.

clauderic avatar Apr 01 '22 13:04 clauderic

@clauderic I wonder we have any workaround for this case?

ducan-ne avatar May 09 '22 10:05 ducan-ne

Not only in Safari, but also on mobile Chrome too. Dragging is cancelling when I start drag item with keyboard open, because keyboard hiding when input loses focus and window resize happen.

muerwre avatar Jul 14 '22 06:07 muerwre

The main thing that needs to be done for this to work properly is to update the measurements of the scrollable ancestor bounding rectangles when they resize.

Hi @clauderic, I will have time to work on this issue in the next several weeks. If you are able to point out where in the code those measurements are, I'd be happy to take a look. Thanks!

adriantrunzo avatar Jul 27 '22 20:07 adriantrunzo

@clauderic I wonder we have any workaround for this case?

@ducan-ne The workaround I described above is to make sure that the HTML <body> does not scroll. The body scrolling is what triggers the mobile browser UI to collapse and expand. In other words, apply some style rules like overflow: hidden; height: 100vh; width: 100vw; to the body element and put your content in a child element that is scrollable. Take a look at the dnd-kit Storybook examples to see an example of this kind of page styling: Screen Shot 2022-07-27 at 12 15 10 PM

Obviously, this workaround is not feasible in all cases. It will also not fix the keyboard hiding trigger that @muerwre pointed out.

adriantrunzo avatar Jul 27 '22 20:07 adriantrunzo

Is there any quick fix for this?

taejs avatar Aug 20 '22 15:08 taejs

Assuming the draggable element is an input or textarea not expected to work even after the keyboard is evoked.

In ios you may need to use window.visualViewport to get the size of the window and listen for window changes.

image

StringKe avatar Sep 02 '23 15:09 StringKe