From a5507287965aa0989fdc25a2a126ed9194df2458 Mon Sep 17 00:00:00 2001 From: SeanLebida Date: Thu, 1 Oct 2026 13:09:04 -0400 Subject: [PATCH] fix(map): dismiss place detail on move and keep chrome above it Lower country-border-popup below the mode sheet and layer widget, enable closeOnMove/closeOnClick/closeButton, and clear the popup on empty-map taps so detail no longer sticks over UI. --- .../2026-10-01-map-detail-dismiss-stacking.md | 12 ++++++++++++ src/map/MapProvider.tsx | 9 ++++++++- src/styles/global.css | 18 ++++++++++++++++-- 3 files changed, 36 insertions(+), 3 deletions(-) create mode 100644 learnings/2026-10-01-map-detail-dismiss-stacking.md diff --git a/learnings/2026-10-01-map-detail-dismiss-stacking.md b/learnings/2026-10-01-map-detail-dismiss-stacking.md new file mode 100644 index 0000000..2338be4 --- /dev/null +++ b/learnings/2026-10-01-map-detail-dismiss-stacking.md @@ -0,0 +1,12 @@ +# Map tap detail: dismiss + stacking (2026-10-01) + +## Symptom +Tapping the map opened a country/feature detail popup that stayed overlaid on other UI, with no clear way to dismiss when moving on. + +## Fix +- Drop `.country-border-popup` z-index from 1000 → 8 (below mode sheet / tab bar / layer widget). +- `closeOnMove: true`, `closeOnClick: true`, `closeButton: true` on the MapLibre Popup. +- Empty-map tap calls `popup.remove()` so a leftover detail cannot linger. + +## Gate +Open detail → pan or tap elsewhere → detail gone; chrome (sheet, layers) stays above the popup. diff --git a/src/map/MapProvider.tsx b/src/map/MapProvider.tsx index 037e3b3..7002c2d 100644 --- a/src/map/MapProvider.tsx +++ b/src/map/MapProvider.tsx @@ -167,9 +167,13 @@ export function MapProvider({ children }: { children: ReactNode }) { countryMarkers.forEach(({ marker }) => marker.addTo(map)); // Click handler on country shading to show info popup + // closeOnMove + closeOnClick: dismiss when the user pans or taps elsewhere. + // closeButton: explicit close. Z-index stays below mode sheet / chrome (see CSS). const popup = new maplibregl.Popup({ - closeButton: false, + closeButton: true, closeOnClick: true, + closeOnMove: true, + maxWidth: '280px', className: 'country-border-popup', }); @@ -288,8 +292,11 @@ export function MapProvider({ children }: { children: ReactNode }) { `; popup.setLngLat(e.lngLat).setHTML(content).addTo(map); + return; } } + // Empty map tap — clear any open detail so chrome stays usable. + popup.remove(); }); // Hover handler to dynamically change the cursor to a pointer when diff --git a/src/styles/global.css b/src/styles/global.css index cd400aa..2f8ba44 100644 --- a/src/styles/global.css +++ b/src/styles/global.css @@ -193,9 +193,23 @@ a { pointer-events: none; /* never intercept a map click */ } -/* Custom country border details popup */ +/* Custom country border details popup. + Keep below mode sheet (12), tab bar (20), travel strip (26), and the + floating layer widget (100) so the detail never buries chrome. */ .country-border-popup { - z-index: 1000; + z-index: 8; +} +.country-border-popup .maplibregl-popup-close-button { + color: var(--text-muted); + font-size: 1.1rem; + padding: 0.15rem 0.45rem; + right: 0; + top: 0; +} +.country-border-popup .maplibregl-popup-close-button:hover, +.country-border-popup .maplibregl-popup-close-button:focus-visible { + color: var(--text); + background: transparent; } .country-border-popup .maplibregl-popup-content { background: var(--surface);