Skip to content

fix(app): stop the composer dropzone flickering and showing for text drags - #60746

Merged
Hona merged 2 commits into
devfrom
drop-overlay-flicker
Oct 30, 2026
Merged

Hona merged 2 commits into
devfrom
drop-overlay-flicker

Conversation

@Hona

@Hona Hona commented Oct 30, 2026 •

Copy link
Copy Markdown
Member

Summary

  • Regression from: feat(session-ui): rewrite v2 prompt input #37102 (v2 prompt input rewrite). It mapped every drag type to one drag.enter state, so the text drags that feat(app): drag-n-drop to @mention file #12569 treated as @mention drags now opened the file dropzone. It also added the editor dragleave handler that clears the state.
  • Text drags showed the file dropzone. The document dragover listener treated any drag that carried text/plain as a file drag. When you dragged a selection in the composer, "Drop images, PDFs, or files to add" covered the page.
  • File drags flickered over the composer. The editor's dragleave cleared the drag state every time the pointer moved between the editor's own nodes. The next dragover set it again, so the dropzone unmounted, remounted, and restarted its fade on each move.
  • Fix: The document dragover owns the drag state. The editor no longer sets or clears it. The dropzone opens only for drags that carry Files (from the system) or text/uri-list (file rows from the workspace tree).

Before

drag-before.mp4

After

drag-after.mp4
sequenceDiagram
  participant D as document
  participant E as editor
  participant S as drag state
  Note over D,S: Before: pointer moves from the editor onto its text
  E->>S: dragleave G�� idle (dropzone unmounts)
  D->>S: dragover G�� active (dropzone remounts, fade restarts)
  Note over D,S: After
  D->>S: dragover G�� active (no change)
Loading

Implementation

  • attachments.ts: dragover sets the state from the drag's types:

    function dragType(data: DataTransfer | null) {
      if (data?.types.includes("Files")) return "image"
    
      if (data?.types.includes("text/uri-list")) return "@mention"
    
      return null
    }
  • interaction.ts / editor.tsx: The editor's dragenter only calls preventDefault(), and it has no dragleave handler. onDragLeave is now clearDrag. The session controller calls it when the composer becomes hidden.

  • composer.spec.ts: A new keeper checks two things. A text drag shows no dropzone. When a file drag moves onto the editor's text, the dropzone element stays mounted and visible.

Visual

<svg xmlns="http://www.w3.org/2000/svg" width="240" height="72" viewBox="0 0 240 72" fill="currentColor">
  <rect x="20" y="4" width="200" height="64" rx="6" opacity=".06"/>
  <g opacity=".12">
    <path d="M40 60 L64 12 M64 60 L88 12 M88 60 L112 12 M112 60 L136 12 M136 60 L160 12 M160 60 L184 12 M184 60 L208 12" stroke="currentColor" stroke-width="6"/>
  </g>
  <circle cx="120" cy="24" r="8" opacity=".25"/>
  <path d="M120 20 L120 28 M116 23 L120 19 L124 23" stroke="currentColor" stroke-width="1.6" fill="none" opacity=".8"/>
  <rect x="84" y="38" width="72" height="6" rx="3" opacity=".7"/>
  <rect x="44" y="50" width="152" height="12" rx="4" opacity=".14"/>
  <g>
    <animateTransform attributeName="transform" type="translate" values="0 0;100 0;0 0" dur="3s" repeatCount="indefinite" calcMode="spline" keySplines=".4 0 .2 1;.4 0 .2 1"/>
    <rect x="52" y="46" width="14" height="18" rx="2" opacity=".55"/>
    <path d="M62 54 l5 5 l-2 0 l1.5 3 l-1.5 0.7 l-1.5 -3 l-1.5 1.5 z" opacity=".9"/>
  </g>
</svg>

Copilot AI balanced review requested due to automatic review settings October 30, 2026 23:28
@Hona
Hona requested a review from Brendonovich as a code owner October 30, 2026 23:28

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has insufficient remaining quota. Try requesting a review at a lower effort level.

An organization owner can choose the repository organization as the billing source for reviews requested by members with a paid Copilot license. Learn about Copilot code review billing.

@opencodejr opencodejr Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good. I ran the new composer e2e test on the base: it fails both at the text-drag check (the dropzone shows) and at the file-drag check (the dropzone element is unmounted and remounted when the drag moves onto the editor's text). With this change, both dropzone tests in composer.spec.ts pass. packages/app unit tests and tsc -b are clean. Workspace-tree drags still open the dropzone, because startFileDrag sets text/uri-list.

Public API is unchanged (onDragLeave → clearDrag is internal to the app).

No concerns.

Before

After

@opencodejr opencodejr Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new commit only adds blank lines to the new e2e test for lint. It changes no behaviour, and my earlier check of the fix still applies. Public API is unchanged. No new concerns.

@Hona
Hona merged commit 8b4d98c into dev Oct 30, 2026
20 checks passed
@Hona
Hona deleted the drop-overlay-flicker branch October 30, 2026 23:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants