Skip to content

useDragAndDrop keyboard DnD: findNearestDropTarget selects wrong collection when drag source is last item #10055

@lisatassone

Description

@lisatassone

Provide a general summary of the issue here

When using keyboard DnD with multiple GridList collections that accept the same drag type (e.g. sectioned lists), the initial drop target after pressing Enter to start a drag lands in the wrong collection if the dragged item is at the last position in its parent collection.

Root Cause

Bug 1 (primary): DragManager.findNearestDropTarget() uses top-left corner distance

// DragManager.js
findNearestDropTarget() {
  let dragTargetRect = this.dragTarget.element.getBoundingClientRect();
  for (let i = 0; i < this.validDropTargets.length; i++) {
    let rect = this.validDropTargets[i].element.getBoundingClientRect();
    let dx = rect.left - dragTargetRect.left;
    let dy = rect.top - dragTargetRect.top;
    let dist = dx * dx + dy * dy;
    // ...
  }
}

When drag source is near bottom of its collection, the next collection's top-left corner is geometrically closer than the current collection's top-left corner.

Bug 2 (secondary): draggingCollectionRef not set before DragSession RAF

useDraggableCollectionState stores draggingKeys in a useRef. startDrag(), mutates the ref → no re-render triggered. But useDraggableCollection only calls setDraggingCollectionRef(ref) during render. Since no re-render occurs between onDragStart and the requestAnimationFrame in beginDragging, globalDndState.draggingCollectionRef remains undefinedisInternalDropOperation() returns false for all collections.

🤔 Expected Behavior?

Initial drop indicator appears within the current section (the collection containing the dragged item).

😯 Current Behavior

Initial drop indicator appears in the next section (the geometrically "nearest" collection by top-left corner distance).

💁 Possible Solution

Bug One:
Suggested fix: Use containment check (is drag source inside the collection rect?) or center-to-center distance instead of top-left corner distance.

Bug Two:
Suggested fix: Call setDraggingCollectionRef synchronously in the drag start path (alongside setDraggingKeys), not depend on a render cycle.

🔦 Context

Versions

  • react-aria-components@1.17.0
  • react-aria@3.48.0
  • react-stately@3.46.0

🖥️ Steps to Reproduce

https://codesandbox.io/p/sandbox/naughty-bash-tw5vx2

Version

react-aria-components@1.17.0

What browsers are you seeing the problem on?

Chrome

If other, please specify.

No response

What operating system are you using?

MacOS Tahoe

🧢 Your Company/Team

No response

🕷 Tracking Issue

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions