Summary
When quickly dragging a code snippet out of the Monaco toolbox flyout on iPad the drag sometimes neither inserts the snippet nor fails cleanly. The dragged ghost element stays over the editor and breaks subsequent drag attempts.
Spotted when testing microsoft/pxt#11404 as I did a lot of dragging but repros in live.
Steps to reproduce
- Open the Monaco (JS/Python) editor on an iPad.
- Open a toolbox category flyout.
- Quickly drag/flick a snippet toward the editor. My best repro is to tap Input and drag the first block diagonally up and to the right ~1.5cm.
You might need to try a few times. I made a video but for some reason I can't upload it so here's a screenshot of the broken state post-drag:
Cause
The flyout drag uses pointer listeners (see webapp/src/monacoFlyout.tsx). On a fast touch, iOS Safari can claim the gesture as a scroll/pan and fire pointercancel instead of pointerup. The flyout only listens for pointerup, so blockDragEndHandler doesn't run, leaving the #monacoDraggingBlock ghost in the DOM, plus stale insertionSnippet/dragInfo and #root { overflow: hidden }, which corrupts the next drag. This is a touch-only problem so you can't reproduce with the mouse.
Potential fix
Route pointercancel (and touchcancel) to the existing blockDragEndHandler.
A fast flick may still be interpreted as a scroll rather than completing the insertion, but it now fails cleanly without blocking later drags.
Another option is touch-action: none on the block body, but I'm worried that will conflict with flyout scrolling. Haven't tried it though.
I quickly tried the pointercancel option but it's a bit weird when the flyout just closes without anything happening so raising this in case there are better ideas.
Summary
When quickly dragging a code snippet out of the Monaco toolbox flyout on iPad the drag sometimes neither inserts the snippet nor fails cleanly. The dragged ghost element stays over the editor and breaks subsequent drag attempts.
Spotted when testing microsoft/pxt#11404 as I did a lot of dragging but repros in live.
Steps to reproduce
You might need to try a few times. I made a video but for some reason I can't upload it so here's a screenshot of the broken state post-drag:
Cause
The flyout drag uses pointer listeners (see
webapp/src/monacoFlyout.tsx). On a fast touch, iOS Safari can claim the gesture as a scroll/pan and firepointercancelinstead ofpointerup. The flyout only listens forpointerup, soblockDragEndHandlerdoesn't run, leaving the#monacoDraggingBlockghost in the DOM, plus staleinsertionSnippet/dragInfoand#root { overflow: hidden }, which corrupts the next drag. This is a touch-only problem so you can't reproduce with the mouse.Potential fix
Route
pointercancel(andtouchcancel) to the existingblockDragEndHandler.A fast flick may still be interpreted as a scroll rather than completing the insertion, but it now fails cleanly without blocking later drags.
Another option is
touch-action: noneon the block body, but I'm worried that will conflict with flyout scrolling. Haven't tried it though.I quickly tried the pointercancel option but it's a bit weird when the flyout just closes without anything happening so raising this in case there are better ideas.