From 6434d11384b9b54a2273b3ad36a14fbfff450868 Mon Sep 17 00:00:00 2001 From: Richie Date: Wed, 22 Apr 2026 22:55:26 +1000 Subject: [PATCH] ProvidersStep mobile: unify list-view controls + PackagesStep drill-in fix Controls - Mobile list view's Filters/Sort/view-toggle now match the mobile map view's floating-chip treatment: white fill, neutral-300 border, shadow-sm. On mobile the sort label switches from "Sort: " to a compact "Sort by"; desktop keeps its verbose label. - List/Map toggle font bumped to 14px / 600 (button-small token), so it reads on the same line as Filters + Sort by both on mobile and on the desktop floating pill over the map panel. PackagesStep drill-in - Added a local hasDrilledIn flag so the mobile layout only swaps to the detail view after an explicit user tap on a package. Previously any pre-selection (the demo route seeds selectedPackageId to the first matching package for desktop auto-display) also forced mobile into the detail view, so users arriving from the map drawer saw a single package instead of the list. Back/forward from the detail resets the flag. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../pages/PackagesStep/PackagesStep.tsx | 22 +++-- .../pages/ProvidersStep/ProvidersStep.tsx | 86 ++++++++++++++----- 2 files changed, 78 insertions(+), 30 deletions(-) diff --git a/src/components/pages/PackagesStep/PackagesStep.tsx b/src/components/pages/PackagesStep/PackagesStep.tsx index b4b9e3d..5153220 100644 --- a/src/components/pages/PackagesStep/PackagesStep.tsx +++ b/src/components/pages/PackagesStep/PackagesStep.tsx @@ -1,4 +1,4 @@ -import React, { useEffect } from 'react'; +import React, { useEffect, useState } from 'react'; import Box from '@mui/material/Box'; import { useTheme } from '@mui/material/styles'; import useMediaQuery from '@mui/material/useMediaQuery'; @@ -206,17 +206,25 @@ export const PackagesStep: React.FC = ({ const copy = TIER_COPY[providerTier]; const selectedPackage = packages.find((p) => p.id === selectedPackageId); - // Mobile drill-in: when a package is selected on mobile, swap the list view - // for the detail view. Back button clears selection to return to the list. + // Mobile drill-in: on mobile, the list is the default view — only when the + // user explicitly taps a package do we swap in the detail panel. This + // distinguishes "parent pre-selected first package for desktop auto-display" + // (which should NOT jump to detail on mobile) from "user tapped a package". const theme = useTheme(); const isMobile = useMediaQuery(theme.breakpoints.down('md')); - const mobileShowDetail = isMobile && selectedPackageId != null; + const [hasDrilledIn, setHasDrilledIn] = useState(false); + const mobileShowDetail = isMobile && hasDrilledIn && selectedPackageId != null; + + const handleSelectPackage = (id: string | null) => { + setHasDrilledIn(id != null); + onSelectPackage(id); + }; useEffect(() => { if (mobileShowDetail) window.scrollTo({ top: 0, behavior: 'auto' }); }, [mobileShowDetail]); - const handleLayoutBack = mobileShowDetail ? () => onSelectPackage(null) : onBack; + const handleLayoutBack = mobileShowDetail ? () => handleSelectPackage(null) : onBack; const layoutBackLabel = mobileShowDetail ? 'Back to packages' : 'Back'; // Secondary list suppressed in "show all" mode. @@ -349,7 +357,7 @@ export const PackagesStep: React.FC = ({ description={pkg.description} price={pkg.price} selected={selectedPackageId === pkg.id} - onClick={() => onSelectPackage(pkg.id)} + onClick={() => handleSelectPackage(pkg.id)} /> ))} @@ -385,7 +393,7 @@ export const PackagesStep: React.FC = ({ description={pkg.description} price={pkg.price} selected={selectedPackageId === pkg.id} - onClick={() => onSelectPackage(pkg.id)} + onClick={() => handleSelectPackage(pkg.id)} /> ))} diff --git a/src/components/pages/ProvidersStep/ProvidersStep.tsx b/src/components/pages/ProvidersStep/ProvidersStep.tsx index 160805e..ee9a98c 100644 --- a/src/components/pages/ProvidersStep/ProvidersStep.tsx +++ b/src/components/pages/ProvidersStep/ProvidersStep.tsx @@ -687,7 +687,7 @@ export const ProvidersStep: React.FC = ({ {/* View toggle — text labels on mobile, aligned height with - the buttons */} + the buttons; font matches Filters/Sort (14px / 600) */} = ({ boxShadow: 'var(--fa-shadow-sm)', '& .MuiToggleButton-root': { height: 32, - px: 1.25, + px: 1.5, py: 0, textTransform: 'none', - fontSize: '0.8125rem', - fontWeight: 500, + fontSize: 'var(--fa-button-font-size-sm)', + fontWeight: 600, borderColor: 'var(--fa-color-neutral-300)', bgcolor: 'background.paper', '&:hover': { bgcolor: 'background.paper' }, @@ -961,8 +961,8 @@ export const ProvidersStep: React.FC = ({ height: 'var(--fa-button-height-sm)', px: 1.5, py: 0, - fontSize: '0.8125rem', - fontWeight: 500, + fontSize: 'var(--fa-button-font-size-sm)', + fontWeight: 600, gap: 0.75, border: '1px solid', borderColor: 'divider', @@ -1134,31 +1134,64 @@ export const ProvidersStep: React.FC = ({ gap: 1, }} > - {/* Filters */} + {/* Filters — on mobile, matches the map-view floating chip style + (white fill, neutral-300 border, shadow-sm). On desktop, + default Button small look. */} {filterDialogChildren} - {/* Sort — compact menu button, pushed right */} + {/* Sort — mobile shows a compact "Sort by" text button matching + the Filters chip style; desktop keeps the full "Sort: " + label with its swap icon. */} = ({ - {/* Mobile-only view toggle — switches to the map-first layout */} + {/* Mobile-only view toggle — matches the map-view floating toggle: + text labels (List / Map), white fill, neutral-300 border, shadow, + 14px / 600 type to align with the Filters + Sort by buttons. */} = ({ aria-label="View mode" sx={{ display: { xs: 'inline-flex', md: 'none' }, + flexShrink: 0, + boxShadow: 'var(--fa-shadow-sm)', '& .MuiToggleButton-root': { - px: 1, - py: 0.5, - gap: 0.5, + height: 32, + px: 1.5, + py: 0, textTransform: 'none', - fontSize: '0.75rem', - fontWeight: 500, + fontSize: 'var(--fa-button-font-size-sm)', + fontWeight: 600, + borderColor: 'var(--fa-color-neutral-300)', + bgcolor: 'background.paper', + '&:hover': { bgcolor: 'background.paper' }, '&.Mui-selected': { bgcolor: 'var(--fa-color-brand-100)', color: 'primary.main', @@ -1208,10 +1248,10 @@ export const ProvidersStep: React.FC = ({ }} > - + List - + Map