Skip to content

Preview drag sends one mouse move, so pages never see mousemove after dragstart #36092

Closed

Description

@Daimonke

What happened

The preview_act drag action can't perform drag gestures that a page tracks with mousemove. I tried to crop an image in a canvas editor: its overlay is draggable, the dragstart handler calls preventDefault(), and later mousemove events set the crop's end point. Every drag produced an empty crop, which the editor ignores. The same gesture works with a real mouse and with Playwright page.mouse.move(x, y, { steps: 4 }).

Separately, drag accepts only element locators, so it can't start or end at a chosen point inside one element, such as drawing a selection rectangle on a canvas.

Diagnosis

drag in apps/server/src/preview/ServerBrowserPage.ts calls source.dragTo(target, { timeout }) and passes no steps. Playwright 1.64.1 dragAndDrop then moves to the source, presses the button, makes one mouse.move(target) (steps default to 1) and releases.

In Chromium that single move reaches the page as mousemove before drag detection fires dragstart, so no mousemove arrives after dragstart. A gesture that starts on dragstart and updates on mousemove sees zero length.

PreviewAutomationDragInput (packages/contracts/src/previewAutomation.ts) has only source, target and timeoutMs: no steps, no sourcePosition/targetPosition, no coordinates. The code is the same on main.

Possible fix: pass steps (for example 5 to 10) to dragTo. Optionally expose Playwright's sourcePosition/targetPosition (or x/y) on the drag input.

Steps to reproduce

  1. Serve this page and open it in a preview tab:
<!doctype html>
<div style="display:flex;gap:40px">
  <div id="source" draggable="true" style="width:200px;height:120px;background:#cde">source</div>
  <div id="target" style="width:200px;height:120px;background:#edc">target</div>
</div>
<pre id="log"></pre>
<script>
  let dragging = false;
  const log = (line) => (document.getElementById('log').textContent += line + '
');
  source.addEventListener('dragstart', (e) => { e.preventDefault(); dragging = true; log('dragstart'); });
  addEventListener('mousemove', () => log('mousemove dragging=' + dragging));
  addEventListener('mouseup', () => { log('mouseup'); dragging = false; });
</script>
  1. preview_act with action: "drag", source: "#source", target: "#target".
  2. Read #log.

Expected: at least one mousemove dragging=true line between dragstart and mouseup, as with a real mouse.
Actual: mousemove dragging=false, mousemove dragging=false, dragstart, mouseup.

Version

Desktop app 0.1.10-nightly.20261112.4580. The drag code is unchanged on main (checked at 7e1a058, nightly 20261113.4630).

Environment

Windows 11 Pro 10.0.26200, T3 Code desktop (Nightly), local server, Node 24.19.0. preview_act called from an agent session.

Evidence

Same page, same Chromium, run through Playwright 1.64.1 directly:

dragTo steps=default: mousemove dragging=false, mousemove dragging=false, dragstart, mouseup
dragTo steps=5:       mousemove dragging=false, mousemove dragging=false, dragstart, mousemove dragging=true (x4), mouseup

T3 preview_act drag (same page): mousemove dragging=false, mousemove dragging=false, dragstart, mouseup

Related issues

#17322 is also about dragTo, but it covers a timeout that crashes the server. This issue is about the mouse-move sequence of a successful drag.

Fix applied or workaround

None in T3. Drag by hand in the tab, or run the gesture outside T3 with Playwright page.mouse and steps.

Filed by

Claude Code (claude-opus-5-5), following the t3 triage playbook

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

    via-triageFiled through npx t3 triage

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions