Skip to content

fix(map): rapid mouse drag falls into text-select mode #8

Description

@dvhthomas

Symptom

Drag the map, then drag again rapidly (before the first drag's render settles) → browser interprets the second drag as text-selection. Sticks until the user releases. Selects whatever DOM is underneath the map area.

Reproduces on the live site with a mouse (not touch). Touch input behaves correctly.

Diagnosis

`src/styles/global.css:278-290` already has `touch-action: none !important` on `.map-wrap` with a load-bearing comment explaining why (touch pipeline classifies single-finger touches as scrolls before MapLibre's listeners can claim them). But there is no `user-select` rule at all on `.map-wrap` — only the touch side is protected.

Mouse path is unprotected:

  • `mousedown` on `.map-wrap` → default cascade resolves to `user-select: auto` from the body.
  • Browser interprets the drag as text-selection on whatever's behind the map element.
  • MapLibre's bundled CSS sets `.maplibregl-map { user-select: none }`, but during init or rapid-render gaps, the class isn't yet applied or its cascade is shadowed by an equal-specificity rule.

Proposed fix

Two CSS lines next to the existing `touch-action: none !important` rule:

```css
.map-wrap {
user-select: none;
-webkit-user-select: none;
/* (existing: touch-action: none !important; ...) */
}
```

Mirrors the existing touch-side mitigation. Closes the same gap on the mouse side. Not an aesthetic change — interaction-correctness only.

Acceptance criteria

  • Reproduce the bug on `main` (rapid mouse drag triggers text-select)
  • Apply the fix; verify text-select no longer triggers on rapid mouse drag
  • Verify normal text-selection elsewhere on the page still works
  • Verify touch behavior is unchanged
  • Verify R24 preservation: only the `.map-wrap` rule changes; no other CSS

Related

Scope

Land as its own focused PR after v1 cutover. Out of v1 scope per R24 (CSS preservation), but this is interaction-correctness not aesthetic, so the constraint doesn't strictly apply — it just doesn't need to be in v1's critical path.

🤖 Generated with Claude Code

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions