Skip to content

fix(shell): recover a drop overlay that outlived its drag - #1683

Merged
giswqs merged 5 commits into
mainfrom
fix/issue-1664-stuck-drop-overlay
Aug 4, 2026
Merged

fix(shell): recover a drop overlay that outlived its drag#1683
giswqs merged 5 commits into
mainfrom
fix/issue-1664-stuck-drop-overlay

Conversation

@giswqs

@giswqs giswqs commented Aug 3, 2026

Copy link
Copy Markdown
Member

Fixes #1664

The bug

After importing a style file onto a vector layer through the Layer panel's import dialog, the drag-and-drop overlay ("Drop vector or raster files here to add layers") sat over the map and never went away. Escape did nothing, resizing did nothing, and the only thing that dismissed it was dragging an unrelated file across the window.

Root cause

isDraggingFiles in DesktopShell is a single boolean fed from two independent places:

  • the webview drag handlers, which balance it with dragDepthRef
  • on desktop, Tauri's native onDragDropEvent, which sets it with no counter at all, since the OS reports enter/leave/drop directly

Either feed can strand it. A native leave the OS never delivers leaves the flag set with nothing left to clear it, which is what a modal native file dialog opening mid-drag produces on WebKitGTK, and is how the reporter hit it through the style import dialog on Debian 12. An unbalanced webview enter/leave pair has the same effect by leaving dragDepthRef above zero. That explains every symptom in the report, including why dragging another file across the window was the only workaround: it supplies the missing leave.

The fix

Rather than chase every way the OS can swallow a drag event, recover on two signals that cannot occur while a real drag is in progress: a key press and a pointer button. HTML5 drags suppress mouse events for their duration, and native drags hold a pointer grab, so neither can fire mid-drag and dismiss the overlay out from under a drag the user is actually performing.

  • Escape clears the overlay, which is what the reporter reached for first.
  • A pointer press clears it too, so it heals on the next interaction without the user knowing to press anything.
  • Both reset dragDepthRef, so the two feeds cannot disagree afterward.

Verification

Driven in the real app with Playwright against us_cities.geojson:

before after
Overlay stranded by an unbalanced drag stuck stuck
Escape still stuck cleared
Click still stuck cleared
Balanced drag enter/leave shows/hides shows/hides
Real file drop imports the layer imports the layer

Confirmed the overlay renders and clears correctly in both dark and light themes.

New e2e cover in e2e/drop-overlay.spec.ts: the two recovery tests fail on main and pass here; the balanced-drag guard passes either way. Also ran npm run build and pre-commit on the changed files.

Note on reproduction

The stranded-overlay defect and all four reported symptoms reproduce in a browser. The specific trigger the reporter described (the native GTK file chooser swallowing a drag leave) is desktop-only and I could not drive it directly, since Playwright cannot attach to the Tauri window. The fix is deliberately trigger-agnostic for that reason: it guarantees the overlay can always be dismissed regardless of which side loses the event.

Summary by CodeRabbit

  • Bug Fixes

    • File-drop overlays now dismiss correctly when pressing Escape or clicking, preventing stale overlays from remaining visible.
    • Improved cleanup after interrupted drag-and-drop interactions, including clicks on controls that stop event propagation.
    • Normal file drops continue to import layers and clear the overlay as expected.
  • Tests

    • Added regression coverage for balanced and interrupted file-drag scenarios, including dismissal via Escape, pointer clicks, and completed file drops.

The drag-and-drop overlay is one boolean fed from two independent places.
The webview drag handlers balance it with a depth counter, but on desktop
Tauri's native onDragDropEvent sets it with no counter at all, since the OS
reports enter/leave/drop directly. Either feed can strand it: a native
"leave" the OS never delivers (what a modal native file dialog opening
mid-drag produces on WebKitGTK, which is how the reporter hit it via the
style import dialog), or an unbalanced webview enter/leave pair that leaves
the depth counter above zero. Both leave the overlay covering the map with
nothing left to clear it, which is why neither Escape nor a resize helped
and only dragging another file across the window dismissed it.

Rather than chase every way the OS can swallow a drag event, recover on two
signals that cannot occur while a real drag is in progress: a key press and
a pointer button. HTML5 drags suppress mouse events for their duration and
native drags hold a pointer grab, so neither can fire mid-drag and dismiss
the overlay out from under a drag the user is actually performing.

- Escape clears the overlay, which is what the reporter reached for first.
- A pointer press clears it too, so it heals on the next interaction
  without the user knowing to press anything.
- Both reset the depth counter, so the two feeds cannot disagree afterward.
- Add a data-testid to the overlay and e2e cover for both recovery paths
  plus a guard that a balanced drag still shows and hides it.

Fixes #1664
Copilot AI review requested due to automatic review settings August 3, 2026 19:39
@coderabbitai

coderabbitai Bot commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 088c5a76-ed24-41ca-ba23-f65c17c9a9f2

📥 Commits

Reviewing files that changed from the base of the PR and between be46aa1 and 6a695b8.

📒 Files selected for processing (2)
  • apps/geolibre-desktop/src/components/layout/DesktopShell.tsx
  • e2e/drop-overlay.spec.ts

📝 Walkthrough

Walkthrough

DesktopShell now recovers stranded file-drop overlays after Escape or pointer interaction. Playwright tests cover stale overlay dismissal, balanced drag lifecycles, and GeoJSON layer imports.

Changes

File-drop overlay recovery

Layer / File(s) Summary
Overlay recovery behavior
apps/geolibre-desktop/src/components/layout/DesktopShell.tsx
Escape and pointer interaction reset drag state and hide the overlay. Global listeners are removed during cleanup. The overlay now has a test identifier.
Overlay lifecycle validation
e2e/drop-overlay.spec.ts
Playwright tests simulate file drag events and verify dismissal, balanced drag enter and leave events, and GeoJSON imports.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Suggested reviewers: craun718

Poem

A rabbit guards the drop zone bright,
Escape restores the screen to right.
Pointer presses clear the way,
Balanced drags complete their stay,
GeoJSON layers land just right.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly describes the primary fix for the stale drag-and-drop overlay.
Linked Issues check ✅ Passed The changes address issue #1664 by recovering stale overlays and adding regression tests for keyboard, pointer, balanced-drag, and file-drop behavior.
Out of Scope Changes check ✅ Passed The changes are limited to DesktopShell recovery logic and related end-to-end regression tests.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/issue-1664-stuck-drop-overlay

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint install failed: dependency version conflict. Check your lock file or package.json.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

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.

Pull request overview

Fixes GeoLibre#1664 by adding recovery paths to ensure the file drag-and-drop overlay cannot remain stuck over the map after a drag sequence is interrupted (notably when native drag events don’t deliver a matching leave), and by adding E2E regression coverage.

Changes:

  • Add an “escape hatch” effect in DesktopShell to clear the stranded drop overlay on Escape and on the next pointer press, resetting both isDraggingFiles and dragDepthRef.
  • Add a stable data-testid to the overlay to make its presence/assertions testable.
  • Introduce Playwright E2E tests that intentionally strand the overlay via unbalanced drag events and assert both recovery behaviors plus the normal balanced enter/leave path.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
apps/geolibre-desktop/src/components/layout/DesktopShell.tsx Adds global recovery listeners to clear a stranded drag overlay; adds data-testid for test targeting.
e2e/drop-overlay.spec.ts Adds regression tests covering “stuck overlay” recovery via Escape and pointer press, plus a balanced-drag guard.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread apps/geolibre-desktop/src/components/layout/DesktopShell.tsx Outdated
@github-actions

github-actions Bot commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

🔍 Cloudflare PR preview

Item Value
Site https://fe780338.geolibre-preview.pages.dev
Demo app https://fe780338.geolibre-preview.pages.dev/demo/
Commit 6a695b8

@coderabbitai coderabbitai 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.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/geolibre-desktop/src/components/layout/DesktopShell.tsx`:
- Around line 1839-1844: Update the onKeyDown handler to call clear() for every
keydown event rather than only when event.key is "Escape". Add a regression test
that dispatches a non-Escape key and verifies the overlay state is cleared.

In `@e2e/drop-overlay.spec.ts`:
- Around line 58-65: Add a drop-handler test alongside “a balanced drag still
shows and hides the overlay” that uses the existing file-drag helper to drop
supported GeoJSON, then waits for and asserts the resulting imported layer or
successful drop status. Keep the existing overlay visibility assertions
unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: f2623747-456a-4c19-aa29-e546f5f7659c

📥 Commits

Reviewing files that changed from the base of the PR and between da72fe7 and 6836114.

📒 Files selected for processing (2)
  • apps/geolibre-desktop/src/components/layout/DesktopShell.tsx
  • e2e/drop-overlay.spec.ts

Comment thread apps/geolibre-desktop/src/components/layout/DesktopShell.tsx
Comment thread e2e/drop-overlay.spec.ts
Comment thread apps/geolibre-desktop/src/components/layout/DesktopShell.tsx Outdated
Comment thread apps/geolibre-desktop/src/components/layout/DesktopShell.tsx
@github-actions

github-actions Bot commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

Code review

Bugs

  • Low confidence: the pointerdown recovery listener runs at the bubble phase on window, so any descendant that calls event.stopPropagation() on pointerdown (e.g. startLayerPanelResize in this same file, and similar patterns in other panels) will silently prevent that particular click from clearing a stuck overlay. Escape and clicks on the map canvas itself remain unaffected, so this only narrows — not eliminates — the recovery surface.
  • Low confidence / speculative: the keydown Escape listener is similarly bubble-phase on window. If an in-app Radix Dialog is open and focused while the overlay is stuck, and its own Escape handling stops propagation, the first Escape press might close the dialog instead of clearing the overlay. Couldn't verify Radix's actual propagation behavior in this sandboxed environment (no node_modules), so this is a hypothesis worth a quick manual check rather than a confirmed defect.

Security

  • None found.

Performance

  • None found. The new listeners are only attached while isDraggingFiles is true and are properly cleaned up; no leaks or unnecessary re-subscriptions.

Quality

  • The fix is narrowly scoped, the reasoning in the comment block is clear and matches the actual code (verified dragDepthRef/isDraggingFiles wiring at lines 646, 802, 1673, 1694-1695, 1516-1536), and the new e2e test (e2e/drop-overlay.spec.ts) correctly models both the "unbalanced enter/leave" strand scenario and the balanced-drag control case using the same depth-counter semantics as the production code.
  • No new user-facing strings were added, so no i18n follow-up is needed.

CLAUDE.md

  • No violations noted. The change doesn't touch tile/style host allowlists, the Whitebox catalog, translatable strings, or any of the other mirrored-constant conventions called out in CLAUDE.md.

Overall this is a well-reasoned, minimal, and well-tested fix; the two points above are edge-case hedges on the redundancy of the recovery paths, not blocking issues.

@github-actions

github-actions Bot commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

🔍 GitHub Pages PR preview

Item Value
Site Deploy failed. See the job log.
Demo app Unavailable
Commit 6a695b8

- Listen for keydown and pointerdown in the capture phase rather than the
  bubble phase. Several controls stop propagation before these events reach
  window (startLayerPanelResize in this same file is one, and a focused Radix
  dialog handles its own Escape), which silently defeated the recovery for
  exactly the interaction a user is most likely to try first: clicking a panel
  control while the overlay is stuck. Covered by a new e2e test that presses
  the layer panel resize handle, which fails on the bubble phase.
- Add an e2e test that a real GeoJSON drop still imports a layer and leaves the
  overlay hidden, so the recovery listeners cannot swallow the drop the overlay
  exists to invite. This was verified by hand before but not encoded.
@github-actions

github-actions Bot commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

Code review

I reviewed the state-management fix in DesktopShell.tsx (the new capture-phase Escape/pointerdown recovery effect) and the new e2e/drop-overlay.spec.ts suite, tracing all setIsDraggingFiles/dragDepthRef call sites, the Tauri native onDragDropEvent handler, and the webview drag handlers it interacts with.

Bugs: None found. The recovery effect is correctly scoped (if (!isDraggingFiles) return), its listeners are added/removed with matching capture: true, dragDepthRef is clamped via Math.max(0, …) elsewhere so the reset to 0 can't produce negative counts, and handleDrop/the native drop branch don't gate on isDraggingFiles — so an early overlay dismissal via Escape/pointerdown can't break an in-flight drop. The capture-phase choice on window is justified: startLayerPanelResize's event.stopPropagation() is a React synthetic-event call that only affects React's bubble-phase delegation, so it doesn't prevent this native capture listener (which fires while the event is still traveling down from window) from seeing it — confirmed against startLayerPanelResize in the same file (line 1862).

Security: None found. No injection, unsafe input handling, or secrets involved; the change is purely client-side UI state recovery.

Performance: None found. The listeners are only mounted while isDraggingFiles is true, so there's no added overhead outside an active drag.

Quality: Low confidence — the claim that "neither [keydown nor pointerdown] can fire mid-drag" is solid for pointer events (OS/HTML5 drag holds the pointer grab) but slightly weaker for keydown: Escape reliably cancels drags in mainstream Chromium/Firefox/macOS/Windows, but if some platform/browser combination doesn't cancel the underlying drag on Escape, this would prematurely hide the overlay while a real drag continues. This is cosmetic only (drop handling doesn't depend on isDraggingFiles), so low severity even if it occurs.

CLAUDE.md: No violations. data-testid addition and new e2e spec follow existing repository conventions (e2e/helpers.ts patterns, [data-testid="map-canvas"], layerRow helper), and no new user-facing strings were added that would need i18n catalog updates.

Also verified: data-testid="file-drop-overlay" and aria-label for "Resize Layers panel" (layers.resizePanel in en.json) referenced by the new tests both exist and match; no existing unit/snapshot tests reference the changed overlay markup.

@coderabbitai coderabbitai 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.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@e2e/drop-overlay.spec.ts`:
- Around line 58-69: Replace the synthetic pointerdown dispatch in the
resize-handle test with a complete real pointer gesture, using the locator’s
built-in click action or a page.mouse down/up sequence. Ensure the gesture
supplies an active pointer ID for DesktopShell.startLayerPanelResize and reaches
pointerup so resize state is cleaned up while still verifying the overlay is
dismissed.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 021b57d6-116a-4920-9774-9abccdc4797d

📥 Commits

Reviewing files that changed from the base of the PR and between 6836114 and be46aa1.

📒 Files selected for processing (2)
  • apps/geolibre-desktop/src/components/layout/DesktopShell.tsx
  • e2e/drop-overlay.spec.ts

Comment thread e2e/drop-overlay.spec.ts
@giswqs giswqs mentioned this pull request Aug 3, 2026
Comment thread apps/geolibre-desktop/src/components/layout/DesktopShell.tsx Outdated
@github-actions

github-actions Bot commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

Code review

Bugs

  • No functional bugs found. The recovery mechanism correctly resets both isDraggingFiles and dragDepthRef together, the capture-phase listeners correctly bypass controls that stopPropagation() on bubble (verified by both the code and the added e2e test), and the effect's mount/cleanup lifecycle (gated on isDraggingFiles) avoids leaking listeners.

Security

  • None found — no user input handling, injection, or secret-exposure concerns in this diff.

Performance

  • None found — listeners are only attached while the overlay is visible and are properly removed on cleanup.

Quality

  • Medium-low confidence: the justification comment for why keydown/pointerdown "can never" fire mid-drag conflates HTML5's spec-guaranteed suppression of mouse events with keyboard-event behavior, which isn't actually covered by that spec clause — it's an empirically-observed browser behavior rather than a guarantee. If ever violated in some browser/webview, the overlay could visually desync from an actually-still-live drag (not a crash, self-heals on the next dragenter). Left as an inline comment on DesktopShell.tsx.

CLAUDE.md

  • No violations — the new code follows the file's existing dense "why"-focused comment style, uses data-testid rather than fragile selectors, and the e2e test additions follow the conventions already used elsewhere in e2e/.

Overall this is a well-reasoned, well-tested fix with good regression coverage; only one low-confidence note was raised for consideration.

Comment thread apps/geolibre-desktop/src/components/layout/DesktopShell.tsx Outdated
@github-actions

github-actions Bot commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

Code review

Bugs

  • No functional bugs found. The recovery logic (capture-phase keydown/pointerdown listeners, dragDepthRef reset, effect gated on isDraggingFiles) is internally consistent and correctly handles the interactions it targets, including the "stops propagation before reaching window" case exercised by the new e2e test. High confidence.

Security

  • None found. This change is purely client-side UI event wiring with no new input parsing, network calls, or file-path handling. High confidence.

Performance

  • Negligible impact. The new window listeners are only attached while the overlay is showing and are removed as soon as it clears. High confidence.

Quality

  • DesktopShell.tsx:1826-1843 — the block comment states a keypress "cannot occur while a real drag is in progress," but the nested comment just below it acknowledges that typing can happen mid-drag, which is the actual reason the listener is scoped to Escape only. The two comments are in mild tension; worth tightening the top comment to scope the "cannot occur" guarantee to the pointer listener specifically, since keyboard events aren't suppressed during HTML5/native drags the way mouse events are (in practice this is likely harmless since Escape itself typically cancels the underlying drag, so the observed behavior is probably still correct). Low confidence, non-blocking — posted inline.

CLAUDE.md

  • No violations. The change doesn't touch i18n strings, RTL layout, Tauri CSP allowlists, or any of the generated/mirrored-constant files called out in CLAUDE.md, so none of those checklist items apply here.

Overall this is a well-scoped, well-tested fix with clear reasoning and good e2e coverage of both the recovery paths and the non-regression cases (balanced drag, real drop). Only one minor documentation nit was raised.

- e2e/drop-overlay.spec.ts: drive the resize-handle test with a real
  `click()` instead of `dispatchEvent("pointerdown")`. A synthetic pointer
  event carries no active pointer id, so `startLayerPanelResize`'s
  `setPointerCapture` could throw before the capture-phase recovery was
  exercised, and the gesture never reached `pointerup` to tear the resize
  down. Verified the test still fails when the listeners are moved back to
  the bubble phase, so it remains a real regression test.

- DesktopShell.tsx: scope the "cannot occur during a real drag" claim to
  the pointer listener only. HTML5 drag-and-drop suppresses mouse events
  and a native drag holds an OS pointer grab, but neither spec promises
  keyboard events are withheld, and the inline comment on `onKeyDown`
  already assumed a keypress can arrive mid-drag. Escape is now described
  for what it is: a conventional request to cancel the stranded overlay or
  the drag itself.
// silently defeat the recovery for exactly the interaction the user is most
// likely to try first. Capturing on window runs before any of them.
window.addEventListener("keydown", onKeyDown, true);
window.addEventListener("pointerdown", clear, true);

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.

Minor completeness note (low confidence): recovery only fires on Escape or a pointer press. A keyboard-only user navigating with Tab (no pointer, and not thinking to hit Escape) has no way to dismiss a stranded overlay. Given the reporter's workflow this is a big improvement either way, but it might be worth also clearing on focus-in/Tab if keyboard-only recovery matters here.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Leaving this one as-is, and flagging it for a human call rather than resolving.

Two reasons:

  1. A keyboard-only user is not actually blocked. The overlay is pointer-events-none with no focusable children (DesktopShell.tsx:2616-2626), so it never traps focus or intercepts input — Tab navigation and every control keep working normally underneath it. The stranded overlay is a stale visual affordance, not a modal. And Escape, which does clear it, is the conventional dismiss key for exactly this kind of overlay.

  2. Clearing on focus-in/Tab would reintroduce the desync the previous review round just flagged. As noted in fix(shell): recover a drop overlay that outlived its drag #1683 (comment), keyboard and focus events are not spec-suppressed during a drag. Escape is safe despite that because pressing Escape mid-drag is itself the standard gesture to cancel the drag, so clearing the overlay is the correct outcome either way. Tab and focus changes have no such property: they do not cancel a drag, so clearing on them could hide the overlay while a genuine drag is still live.

Happy to add it if the accessibility angle is worth the tradeoff, but it looked like a net regression rather than a win.

@github-actions

github-actions Bot commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

Code review

Bugs: None found with meaningful confidence. The recovery logic correctly reasons about why pointerdown/keydown can't fire during an active HTML5 or native Tauri drag (the mouse button stays held / the OS holds the pointer grab), the capture-phase listeners correctly run ahead of controls that call stopPropagation() (verified startLayerPanelResize at DesktopShell.tsx:1861 does call it), and resetting dragDepthRef alongside isDraggingFiles keeps the two feeds from disagreeing afterward.

Security: None — no new input handling, no untrusted data paths.

Performance: None significant. The effect re-subscribes its two window listeners on every isDraggingFiles toggle (i.e., possibly several times during one real drag over nested elements), but addEventListener/removeEventListener are cheap enough that this isn't worth flagging as a real problem.

Quality: Low-confidence completeness note posted inline — recovery is keyed off Escape or a pointer press only; a keyboard-only user who never presses Escape (e.g. tabbing through the UI) has no path to dismiss a stranded overlay. This is a large improvement over the prior unrecoverable state either way, so it's a nice-to-have, not a blocker.

CLAUDE.md: No violations — e2e spec correctly lives under e2e/, no translatable strings were added (only a data-testid), and no touched files fall under the other repo-specific mirrored-constant rules.

The fix is well-reasoned, the new e2e tests (e2e/drop-overlay.spec.ts) exercise both recovery paths plus the capture-phase-vs-stopPropagation case and the balanced-drag/real-drop regressions, and I verified the test's [aria-label="Resize Layers panel"] selector matches layers.resizePanel in en.json.

@giswqs
giswqs merged commit 4d3379f into main Aug 4, 2026
38 checks passed
@giswqs
giswqs deleted the fix/issue-1664-stuck-drop-overlay branch August 4, 2026 00:23
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.

[Bug]: Drag-and-drop overlay gets stuck after importing a vector layer style (Desktop 2.4.0)

2 participants