Skip to content

fix(ui): fold the map's mobile filter panel and keep it clear of the map's own controls - #479

Closed
osinho wants to merge 6 commits into
orangecoding:masterfrom
osinho:map-mobile-fixes
Closed

osinho wants to merge 6 commits into
orangecoding:masterfrom
osinho:map-mobile-fixes

Conversation

@osinho

@osinho osinho commented Sep 28, 2026 •

Copy link
Copy Markdown

What does this PR do?

Fixes the map's mobile filter panel (<430px): it covered the whole map by default, sat on top of MapLibre's zoom/compass controls, and its attribution control showed full text over the map until the first pan or zoom. Makes the panel a foldable bottom popup that starts collapsed, keeps it clear of the map's own controls and the attribution "i", and collapses the attribution to its icon on load below the same breakpoint.

Related issue

none

AI disclosure (required)

  • ai:generated - AI produced most or all of this PR. I reviewed it, but it is largely machine written.

Which AI: Claude Code, Sonnet 5
How much: All of the diff across the commits (the mobile stylesheet, the view's JSX, the shared map component's attribution fix, and the one test assertion it required updating).
Why: Iterated against real Chrome screenshots and DOM measurements at several viewport widths to get positioning and z-index right; faster than doing that by hand.

Checklist

  • yarn test:offline passes (or yarn test if the change touches a live provider)
  • yarn lint and yarn format:check pass
  • The change is useful for everybody, not a custom tweak for my own setup
  • I have read and answered the AI disclosure above honestly

osinho and others added 5 commits September 28, 2026 11:14
…phones

On viewports below 430px the map's filter panel (basemap controls plus
every listing filter) covered the whole map, leaving nothing to pan or
tap.

Make it foldable behind a checkbox-driven CSS toggle rather than React
state, so it starts folded on a phone and stays open everywhere else
with no resize listener needed in either direction: Map.mobile.less
pins the body open above the breakpoint and hides the toggle there.
The body's own "Map" heading is hidden on a phone too, since it would
otherwise repeat the fold label word for word once unfolded.

New locale key `map.foldToggle` (the toggle's aria-label), added to
all six languages to keep test/ui/locales.test.js passing.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
… map's own controls

The folded pill, and the panel it opens into, sat in the same top-right
column the desktop dropdown uses. At 430px that column is nearly as
wide as the map, so both landed on top of the zoom/compass controls in
the opposite corner (pushed there by the search box) - the same
overlap the fold was meant to fix, just for a shorter box.

Anchor both to the bottom-left instead: folded, a compact pill sized
to its text rather than the full-width bar; open, a bottom sheet with
its own scroll rather than pushing further down the page. Bottom-left
also keeps clear of the attribution control's "i" in the opposite
corner, which runs its full text - not yet the icon it collapses to -
until the map is first panned or zoomed.

Positioned absolute against `.map-shell__ui` (stretched to the map's
own bounds here, where the panel is its only child) rather than fixed
against the viewport, which runs under the app's own sidebar and would
have put the panel half behind it.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Moved from its earlier spot well above the bottom edge - which existed
only to clear the attribution control's expanded text - to the same
row as its "i", on the opposite corner. The two still overlap until
the map is first panned or zoomed, since that text runs its full
width until then; the pill's ancestor already outranks the attribution
control's own stacking context (`.map-shell__ui` at z-index 10 vs. the
control's z-index 2, see Map.less), so the pill stays on top and
clickable rather than the reverse.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
`.map-panel` drew one growing box for both: folded, its own padding
and background wrapped the pill in a visible card of its own, and
open, the same box grew to include the filters below it, carrying the
pill up from the map's bottom edge to the top of that box.

Split them instead. `.map-panel` itself now renders nothing (`display:
contents`) - the pill and the popup are its own two children, each
positioned and boxed independently against `.map-shell__ui`. The pill
stays put in the map's bottom-left corner whether the popup is open or
not; the popup is its own floating box anchored just above the pill's
fixed position rather than one shape growing out of it.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…n narrow maps

Its own compact mode still opened on load with its full attribution
text showing rather than the icon it collapses to on the first pan or
zoom - a paragraph of text sitting over the map, on a page nobody had
touched yet. That open state runs on MapLibre's own
`maplibregl-compact-show` class, not the `<details>` element's native
`open` state (maplibre-gl.css keys the text's `display` off the class
alone), so removing it once, right after the control is created, is
what actually collapses it; `_toggleAttribution` still adds and
removes that same class on a click, so the "i" keeps opening and
closing it exactly as before.

Gated to maps at or under 430px, the breakpoint Map.mobile.less's own
fold already uses: a wide desktop embed keeps the attribution it had.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@orangecoding

Copy link
Copy Markdown
Owner

@osinho This neither has a description nor does it have the mandatory checks fullfilled.

…text

Map.jsx now wraps the group heading's text in its own span (a prior
commit, so Map.mobile.less can hide the text alone on a phone and
leave the fullscreen button next to it visible) - the assertion
checking the two sit on the same heading needed the closing tag added
to keep matching.

ai:generated
Which AI: Claude Code, Sonnet 5
How much: the whole diff, one line plus its comment
Why: fixing a test broken by an earlier Claude Code change in this same PR

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@osinho osinho changed the title Map mobile fixes fix(ui): fold the map's mobile filter panel and keep it clear of the map's own controls Sep 28, 2026
@osinho

osinho commented Sep 28, 2026

Copy link
Copy Markdown
Author

@orangecoding - also, my apologies on this one - when you have time, pls recheck. thanks

@orangecoding

Copy link
Copy Markdown
Owner

Thanks @osinho, realy good catch! The panel covering the whole map on phones is a real problem.

I wont merge this one though. The new styles hit the shared map classes globaly (listing detail and job form maps break on phones, the desktop panel loses its spacing) and the OSM atribution shouldn't be hidden on load. I'll push my own fix to master in a bit, so closing this. Thanks again!

orangecoding added a commit that referenced this pull request Sep 29, 2026
On a phone the panel column is as wide as the map, and the panel (the
basemap switches, every listing filter and the legend) is taller than
what the address search leaves of it, so it covered the whole map
before anyone had asked for a single filter.

Below 768px, the width the listing detail folds its cards at, the
panel now starts folded behind its own heading: a button with
aria-expanded that leaves a small chip in the panel's corner, clear of
the zoom controls and the attribution. What is folded away is not
rendered at all, so the price slider measures its track once it is on
screen. The fullscreen button stays on the heading row either way, and
while folded the chip counts the filters that are hiding pins, read
from the address bar, so an emptier map explains itself after the trip
to a listing and back.

Wider screens are unchanged: the heading stays plain text and the panel
keeps its markup. PHONE_BREAKPOINT moves to hooks/screenWidth.js so both
views read the same number.

Reported in #479.
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.

2 participants