Skip to content

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

@dvhthomas

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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions