Skip to content

fix: map attribution starts collapsed — stop overlapping the planner sheet (#33)#42

Merged
DocGerd merged 4 commits into
mainfrom
fix/33-attribution-collapse
Jul 16, 2026
Merged

fix: map attribution starts collapsed — stop overlapping the planner sheet (#33)#42
DocGerd merged 4 commits into
mainfrom
fix/33-attribution-collapse

Conversation

@DocGerd

@DocGerd DocGerd commented Jul 16, 2026

Copy link
Copy Markdown
Owner

On narrow screens the MapLibre attribution loaded as an expanded ~600 px bar overlapping the bottom sheet — it intercepted taps aimed at the "Route planen" button (the primary on-boat flow, degraded since #24 moved e2e coverage to phone width and exposed it).

Closes #33

Root cause (established against maplibre-gl 5.24 source)

The issue's premise — "compact attribution renders collapsed under 640 px at add time" — is outdated for MapLibre 5.x: _updateCompact() always starts the compact control expanded (open + maplibregl-compact-show) the first time attributions become non-empty; the only upstream auto-collapse is bound to map drag, and the expansion is strictly one-shot. There is no configuration option for start-collapsed.

Fix

collapseAttributionAtLoad() in MapView: a MutationObserver on the control's class attribute removes maplibregl-compact-show once, as a microtask — before first paint — exactly mirroring upstream's own drag-collapse (leaves open as drag-collapse does). It runs at every viewport width (review round 2 dropped an initial wide-layout gate: a session loading wide then narrowed would have kept the overlapping bar; collapsed-but-expandable is CC-BY/ODbL-compliant in both layouts). After the one-shot it disconnects — a user who expands stays expanded; disposer on unmount; touches only the stable public CSS-contract classes, so a future upstream rename degrades gracefully to the old expanded bar, never breakage.

Honest e2e coverage restored (review Finding B from #32)

plan.spec's unconditional collapse-click workaround is removed. The spec now asserts the contract: attribution collapsed at load on the phone viewport (the primary regression guard — it fails if the fix is removed), expandable by tap with the full notice visible and re-collapsible (license-compliance proof), and the "Route planen" click landing with no collapse click.

Verification

  • typecheck / lint clean; MapView + App unit tests 30 passed (incl. an always-collapse pin that fails if a viewport gate is ever re-added, one-shot/user-expansion, disposer, detached-container no-op).
  • Full e2e 4/4 both rounds; fixture restored.
  • Real-browser fresh loads at 1440×900 and 375×667: collapsed at load, sheet unobstructed, expand/re-collapse by tap (screenshots), 0 console errors.
  • Per-PR reviewer: round 1 Approve (root-cause claims verified line-by-line in maplibre-gl 5.24; CSS-contract stability confirmed) with 2 Minors; round 2 Approve (both resolved; rename and the wide-viewport behavior change explicitly blessed).

🤖 Generated with Claude Code

Patrick Kuhn and others added 3 commits July 16, 2026 16:58
MapLibre 5.x's compact AttributionControl always enters the DOM expanded
(_updateCompact adds maplibregl-compact-show together with
maplibregl-compact the moment the first attribution string arrives) and
only the first map drag collapses it — the "renders collapsed under
640px at add time" behavior assumed in the issue does not exist in 5.x.
Below the 1024px breakpoint the expanded ~600px bar overlays the bottom
sheet and intercepts pointer events aimed at the full-width
"Route planen" button.

MapView now swallows that one-shot auto-expansion in the bottom-sheet
layout: a MutationObserver on the control's class attribute reproduces
upstream's own drag-collapse (_updateCompactMinimize — remove
maplibregl-compact-show, nothing else) in a microtask, before the
expanded bar can paint. Only documented CSS-contract classes are
touched; the toggle button keeps working, so the attribution stays one
tap away (CC-BY/ODbL: collapsed-but-expandable is compliant). Wide
layouts keep upstream behavior — nothing overlaps the map column there.

plan.spec.ts drops the unconditional collapse-click workaround
(PR #32 review Finding B) and asserts the fixed contract instead:
collapsed on load at phone width, expandable + re-collapsible by tap,
and the plan click landing with NO collapse click as the interception
regression guard. MapView.test.ts covers the helper's one-shot,
wide-gate, and disposer semantics; App.test.tsx's FakeMap gains
getContainer() (file also picked up formatter-hook reformatting).

Closes #33

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…review r1)

Review round 1, two accepted Minors:

1. Drop the load-time wide-layout media-query gate: it was read once at
   map creation, so a session loaded at >=1024px and then narrowed kept
   the expanded bar overlapping the sheet. The one-shot collapse now
   runs at every viewport width (helper renamed
   collapseAttributionUnderBottomSheet -> collapseAttributionAtLoad);
   collapsed-but-expandable is CC-BY/ODbL-compliant in both layouts.
   The wide-gate unit test becomes an always-collapse pin (re-adding a
   gate must fail it).

2. plan.spec.ts part-3 comment overstated the guard: part 2 re-collapses
   the attribution before the plan click, so part 1's load-state class
   assertion is the primary regression guard and part 3 is
   belt-and-suspenders. Comment only.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…lens round)

Accepted lens findings, item by item:

1. App.test.tsx: revert the whole-file prettier reflow (format-on-edit
   hook churn; prettier is not in the CI gate and the reflow maximized
   conflict surface with feat/38-39) — keep ONLY FakeMap.getContainer().
   Reapplied from main via git apply so the diff vs main is the single
   5-line hunk.
2. MapView.test.ts: test name drops the "review round 1" process
   reference.
3. MapView.tsx: "documented CSS contract classes / stable styling API"
   softened to "CSS classes MapLibre itself ships styles for in
   maplibre-gl.css (a de-facto-stable surface; no JS internals)" —
   MapLibre nowhere documents its class names as public API.
4. MapView.tsx: CC-BY/ODbL compliance claim attributed as the position
   #33 accepted, noting upstream's compact docs recommend not
   collapsing where the bar fits and why the wide layout trades that.
5. MapView.tsx: expansion persists until first drag OR a toggle tap
   (both run the collapse path), not "only the first map drag".
6. MapView.test.ts: "re-adding a gate must fail this test" scoped to
   the wide-skip polarity; other matchMedia gates crash the un-stubbed
   tests instead (jsdom has no matchMedia).
7. MapView.tsx: control enters compact mode expanded — it enters the
   DOM empty/non-compact at onAdd; compact+show arrive with the first
   attribution string.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Comment thread app/src/components/MapView.test.ts
Comment thread app/src/components/MapView.tsx
Comment thread app/src/components/MapView.tsx
Comment thread app/src/components/MapView.tsx
Comment thread app/src/components/MapView.tsx
Comment thread app/src/components/MapView.test.ts
Comment thread app/src/components/MapView.tsx
Comment thread app/src/App.test.tsx
@DocGerd
DocGerd merged commit 911a216 into main Jul 16, 2026
2 checks passed
@DocGerd
DocGerd deleted the fix/33-attribution-collapse branch July 17, 2026 14:21
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.

Narrow screens: expanded map attribution overlaps bottom-sheet content

1 participant