ProvidersStep: extract MapProviderDrawer + unify control chrome + fix search button drift

- New molecule MapProviderDrawer lifts the mobile-map bottom drawer out
  of ProvidersStep (~120 lines): Paper + close-X header + single-pin
  ProviderCard content / cluster-list content + slide-up animation.
  Props: `active: ProviderMapActiveState | null`, `onClose`,
  `onSelectProvider`, `onDrillIntoProvider`. Three Storybook states
  (SingleProvider, Cluster, ClusterPair, Closed) so the drawer can be
  iterated without a live map. ProvidersStep now consumes it as a
  single line wired to mapRef.clearActive + mapRef.drillIntoProvider.

- Shared visual tokens for the control cluster (Search, Filters, Sort by,
  List/Map toggle) factored into a CONTROL_CHROME constant and three
  typed sx objects (controlButtonSx, controlToggleSx, controlInputSx,
  filterTriggerSx) so all four controls share the same outline, radius,
  fill, and shadow across mobile list, mobile map, and desktop. Desktop
  map-panel floating toggle also re-threaded through controlToggleSx.

- Mobile list control order now matches mobile map: Sort by is grouped
  left next to Filters (not pushed right with a ml:auto wrapper), and
  the List/Map toggle is right-pinned via ml:auto on xs. Desktop keeps
  Sort pushed right (no toggle rendered on desktop in this slot).

- Fix: the magnifying-glass commit button was drifting 19–30px left as
  the input filled with chips / draft text. Root cause: overriding
  `InputProps.endAdornment` on Autocomplete bypasses MUI's
  `.MuiAutocomplete-endAdornment` absolute positioning, leaving our
  `.MuiInputAdornment-positionEnd` as `position: static` in flex flow.
  controlInputSx now re-absolutely-anchors the end adornment at the
  right edge and reserves `pr: 5` so input content can't slide under it.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-23 09:39:52 +10:00
parent 6434d11384
commit 30ec88ceaf
6 changed files with 566 additions and 368 deletions

View File

@@ -26,6 +26,38 @@ Each entry follows this structure:
## Sessions
### Session 2026-04-23 — ProvidersStep polish + mobile map-first layout + deploy
**Agent(s):** Claude Opus 4.7 (1M context)
**Work completed:**
- **ProvidersStep desktop polish** (Track 1 of the 2026-04-22 handoff):
- Sort button now reads `Sort: <value>` (was a bare "Recommended" indistinguishable from a filter); price sort labels cleaned of their internal colons to avoid double-colon rendering.
- Results count bolds the number in primary text.
- `viewMode` toggle on the map panel kept as the mobile affordance (desktop toggle still visible but unchanged per user).
- **Sticky search — committed-chip pattern (D046):** replaced the raw `TextField` with an `Autocomplete multiple + freeSolo` capped at 1 location. Typing produces a draft; Enter or the right-hand primary search-icon button commits to an FA Chip (grey/neutral), tap X to clear. Icon spacing tightened, focus ring stripped on the search + Filters + Sort by controls per user call.
- **Mobile map-first layout (D045):** on `xs` + `viewMode=map`, ProvidersStep branches to a custom layout: nav + full-bleed map + floating control card (search + Filters + Sort by + `List|Map` toggle) + bottom drawer + help bar. h1 + subhead dropped on mobile map view to save vertical space; remain on desktop and mobile list. Drawer slides up on pin/cluster tap, slides down on close X. Single-pin drawer renders a `ProviderCard` edge-to-edge (entire card clickable → onSelectProvider); cluster drawer renders an inline list of verified-slot + name + location + rating + "From $X" rows, tap a row to drill in (pan+zoom + swap drawer content to the single-pin card). Close X lives in a 40px header strip so it never overlaps the Verified badge.
- **ProviderMap externalisable popups (D047):** opt-in `externalisePopups` prop + `onActiveChange` callback + imperative `ProviderMapHandle` (`clearActive`, `drillIntoProvider`). Desktop behaviour unchanged when these aren't used; mobile drawer consumes them. `forwardRef` type changed from `HTMLDivElement` to `ProviderMapHandle`; no existing callsite passes a DOM ref so safe.
- **MapPin verified icon:** inline Material Verified (outlined) SVG on the left of the name for verified providers. Inline SVG, not `@mui/icons-material`, because MapPin is mounted via `createRoot` outside the ThemeProvider. Max label width bumped 180→210px.
- **Mobile cluster drawer rows:** verified icon now aligns with the name's top line (matches desktop `ClusterPopup` fix from D043 refinement) + new right-aligned "From $X" price column.
- **Controls unified across mobile views:** mobile list-view sticky controls match the map-view floating chips — white fill, neutral-300 border, shadow-sm, 32px height, 14px/600 text. Mobile sort label switches from "Sort: <value>" to compact "Sort by" (desktop keeps verbose label). Desktop map-panel floating toggle resized to match Filters/Sort button height + type.
- **Filter dialog cleanup (desktop + mobile):** Location field removed (the sticky search is primary); Funeral-type chips bumped small → medium; Reset filters button always renders (disabled when no filters active); provider-feature switches (Verified only, Online arrangements) align to the first text line.
- **PackagesStep mobile drill-in bug fix:** added a local `hasDrilledIn` flag so the mobile layout only swaps to the detail view after an explicit user tap on a package. Previously the demo route seeding `selectedPackageId` to the first matching package (for desktop auto-display) also forced mobile into the detail view — users arriving from the map drawer saw a single package instead of the list. Back/forward from the detail resets the flag.
- **Drawer close animation:** `drawerOpen` now excludes the `exiting` phase so tapping the close X slides the drawer down immediately instead of lingering with an opacity fade-back-in (bug was: transform and opacity transitions interleaving wrong).
- **Whitelist localhost** for the Google Maps API key (user added `http://localhost:5180/*` and `http://localhost:6006/*` to HTTP referrer restrictions), unblocking local map/drawer end-to-end testing.
- **Preflight + deploy:** all checks pass (TS, Storybook build, token sync, ESLint, Prettier). Hex-colour warnings all pre-existing in HomePage. Deployed to `https://parsons.tensordesign.com.au/arrangement/`.
**Decisions made:** D045, D046, D047 (see decisions-log).
**Open questions:**
- User flagged "still more edits to be done" at checkpoint — pending list will come in the next session.
**Next steps:**
- Pick up the user's remaining ProvidersStep polish items.
- Process the `00-Inbox/Mobile list-mode layout for ProvidersStep + ProviderMap.md` note (now implemented — can be archived when the user runs `/process-inbox`).
---
### Session 2026-04-22 — Session-end handoff
**Status at end of session:** Map work reached a stable checkpoint. User asked to resume in a new session rather than continue accumulating context. All work committed.