Skip to content

Touch drag on mobile (iOS): page scrolls back to the drag source after the drop, when the page auto-scrolled during the drag #3045

Description

@ihordubas99

What’s broken?

On a document long enough to scroll, dragging content to a position that is off-screen (so the page auto-scrolls during the drag) and dropping it makes the page jump away from the drop - back to roughly where the drag started.

The content itself lands correctly; only the scroll position is wrong, so the user loses sight of what they just moved.

The precondition is that the page must auto-scroll during the drag. A short drag entirely within the viewport shows nothing, which is why the bug looks intermittent.

Where it comes from: SideMenu.onDrop uses pmView.dragging as its only "this drag belongs to my editor" signal. For a drag the browser carried out itself, dragging is null at drop time, so a same-editor drop falls into the cross-editor branch and the selection is collapsed to the pre-drag anchor:

packages/core/src/extensions/SideMenu/SideMenu.ts:546-564 (0.54.0)

if (isDropPoint) {
  if (this.pmView.dragging) {
    // Do not collapse selection when text content is being dragged
    return;
  }
  // Because the editor selection is unrelated to the dragged content, we
  // don't want PM to delete its content. Therefore, we collapse the selection.
  this.pmView.dispatch(
    this.pmView.state.tr.setSelection(
      TextSelection.create(
        this.pmView.state.tr.doc,
        this.pmView.state.tr.selection.anchor, // <- the selection from BEFORE the drag
      ),
    ),
  );
  return;
}

The jump itself is then ProseMirror doing what it is told: DOMObserver.flush() -> EditorView.scrollToSelection() restores and scrolls to view.state.selection, which now points at the drag source instead of the drop.

A correct fix would resolve the position from the drop coordinates (posAtCoords) rather than reusing the stale pre-drag anchor.

What did you expect to happen?

After a drop, the viewport should stay at the drop location (or the moved content should be scrolled into view) - not scroll back to where the drag started. The selection after the drop should refer to the dropped content, not to the pre-drag position.

Steps to reproduce

  1. Create an editor with enough content to scroll the page — e.g. useCreateBlockNote({ initialContent }) with ~70 plain paragraphs, on a page that scrolls itself (no custom scroll container needed).
  2. Select a line somewhere in the middle and start dragging it via the drag handle.
  3. Drag to the very bottom edge of the viewport and hold there, so the page auto-scrolls and the drag source leaves the viewport.
  4. Drop.
  5. The page jumps back to the drag source instead of staying at the drop. The reverse direction works the same way: drag from the very bottom back up to a position that requires auto-scrolling.

BlockNote version

v0.54.0

Environment

IOS(Safari + Firefox)

Additional context

Originally reported against our product (OpenProject), then reproduced on a clean setup with nothing but @blocknote 0.54.0, React and Vite - no application code, no custom schema.

Contribution

  • I'd be interested in contributing a fix for this issue

Sponsor

  • I'm a sponsor and would appreciate if you could look into this sooner than later 💖

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    needs-triageIssue has not yet been reviewed or classified by maintainers.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions