motiondivision / motiondivision/motion

[BUG] `snapToCursor` accumulates position drift on repeated drags with initial coordinates

Open
#3,805 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
TypeScript
Stars
33.7k
Forks
1.4k
Avg merge
1d 10h
Merged PRs (30d)
14

Description

Description

We discovered this while testing React Motion parity in @humanspeak/svelte-motion. After noticing repeated snap-to-cursor drift in our Svelte implementation, we independently reproduced the same behavior using public React Motion APIs.

When an element has initial x/y coordinates, the first controlled drag snaps correctly. Subsequent starts progressively offset the element from the pointer.

Reproduction

StackBlitz reproduction

The example uses:

const controls = useDragControls();

<button
  onPointerDown={(event) =>
    controls.start(event, { snapToCursor: true })
  }
>
  Start Initial Drag
</button>

<motion.div
  drag
  dragControls={controls}
  dragListener={false}
  dragMomentum={false}
  initial={{ x: 100, y: 40 }}
/>

Steps to reproduce

  1. Press and hold Start Initial Drag.
  2. Move the pointer approximately 150 pixels right and 50 pixels down.
  3. Release.
  4. Repeat the same gesture from the button several times.

Expected behavior

Every pointerdown should center the element beneath the pointer, regardless of its previous position. Repeating the same gesture should produce the same final position.

Actual behavior

Subsequent starts accumulate an offset. The element drifts upward and away from the pointer instead of centering beneath it.

Versions

  • motion, framer-motion, motion-dom: 13.2.0
  • react, react-dom: 19.1.1
  • Reproduced in Chromium.

Investigation

The snap calculation appears to combine a stored projection layout measurement with the changing current motion value, causing the correction to accumulate across sessions.

This may be related to #3445, which addressed first-drag snapping with initial coordinates. We haven’t bisected the history to establish when the repeated-start behavior was introduced.

We have a failing real-browser regression test in our Svelte repository and would be happy to contribute a focused upstream fix with browser regression coverage.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the linked StackBlitz reproduction and inspect the drag snap calculation, especially how projection layout measurements interact with current motion values. Compare the behavior with PR #3445, then reproduce the repeated-start drift and add focused browser regression coverage matching the reported gesture.

Written by the indexing model from the issue text.

Assessment

Tech stack
react, typescript
Domain
frontend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
62/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.