From e67c6342e9198fa4c7225bb7500400a034e42c89 Mon Sep 17 00:00:00 2001 From: Richie Date: Tue, 31 Mar 2026 17:09:52 +1100 Subject: [PATCH] Refine control bar: single-line layout, compact sort, labelled toggle MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - All controls on one line: [List|Map] [Filters] [↕ Recommended] - Sort: compact menu button replaces bulky TextField select - View toggle: "List" / "Map" text labels alongside icons - Results count: own line below controls - Sort pushed right with ml:auto for visual separation Co-Authored-By: Claude Opus 4.6 (1M context) --- .../pages/ProvidersStep/ProvidersStep.tsx | 99 ++++++++++------- src/components/pages/VenueStep/VenueStep.tsx | 100 +++++++++++------- 2 files changed, 126 insertions(+), 73 deletions(-) diff --git a/src/components/pages/ProvidersStep/ProvidersStep.tsx b/src/components/pages/ProvidersStep/ProvidersStep.tsx index 6f9149a..8c4772c 100644 --- a/src/components/pages/ProvidersStep/ProvidersStep.tsx +++ b/src/components/pages/ProvidersStep/ProvidersStep.tsx @@ -6,8 +6,10 @@ import Autocomplete from '@mui/material/Autocomplete'; import FormControlLabel from '@mui/material/FormControlLabel'; import Slider from '@mui/material/Slider'; import MenuItem from '@mui/material/MenuItem'; +import Menu from '@mui/material/Menu'; import ToggleButtonGroup from '@mui/material/ToggleButtonGroup'; import ToggleButton from '@mui/material/ToggleButton'; +import SwapVertIcon from '@mui/icons-material/SwapVert'; import ViewListOutlinedIcon from '@mui/icons-material/ViewListOutlined'; import MapOutlinedIcon from '@mui/icons-material/MapOutlined'; import LocationOnOutlinedIcon from '@mui/icons-material/LocationOnOutlined'; @@ -15,6 +17,7 @@ import type { SxProps, Theme } from '@mui/material/styles'; import { WizardLayout } from '../../templates/WizardLayout'; import { ProviderCard } from '../../molecules/ProviderCard'; import { FilterPanel } from '../../molecules/FilterPanel'; +import { Button } from '../../atoms/Button'; import { Chip } from '../../atoms/Chip'; import { Switch } from '../../atoms/Switch'; import { Typography } from '../../atoms/Typography'; @@ -239,6 +242,9 @@ export const ProvidersStep: React.FC = ({ ? 'Take your time exploring providers. You can always come back and choose a different one.' : 'These providers are near your location. Each has their own packages and pricing.'; + // ─── Local state ─── + const [sortAnchor, setSortAnchor] = React.useState(null); + // ─── Price input local state (commits on blur / Enter) ─── const [priceMinInput, setPriceMinInput] = React.useState(String(filterValues.priceRange[0])); const [priceMaxInput, setPriceMaxInput] = React.useState(String(filterValues.priceRange[1])); @@ -365,45 +371,14 @@ export const ProvidersStep: React.FC = ({ sx={{ mb: 1.5 }} /> - {/* Control bar — results count, sort, view toggle, filters */} + {/* Control bar — view toggle, filters, sort on one line */} - {/* Results count — left */} - - {providers.length} provider{providers.length !== 1 ? 's' : ''} found - - - {/* Sort */} - onSortChange?.(e.target.value as ProviderSortBy)} - size="small" - aria-label="Sort providers" - sx={{ - minWidth: 160, - '& .MuiOutlinedInput-root': { fontSize: '0.813rem' }, - '& .MuiSelect-select': { py: '5px' }, - }} - > - {SORT_OPTIONS.map((opt) => ( - - {opt.label} - - ))} - - {/* View toggle */} = ({ aria-label="View mode" sx={{ '& .MuiToggleButton-root': { - px: 1, + px: 1.5, py: 0.5, + fontSize: '0.75rem', + fontWeight: 500, + gap: 0.5, border: '1px solid', borderColor: 'divider', + textTransform: 'none', '&.Mui-selected': { bgcolor: 'var(--fa-color-brand-100)', color: 'primary.main', @@ -427,10 +406,12 @@ export const ProvidersStep: React.FC = ({ }} > - + + List - + + Map @@ -608,7 +589,53 @@ export const ProvidersStep: React.FC = ({ + + {/* Sort — compact menu button, pushed right */} + + + setSortAnchor(null)} + anchorOrigin={{ vertical: 'bottom', horizontal: 'right' }} + transformOrigin={{ vertical: 'top', horizontal: 'right' }} + > + {SORT_OPTIONS.map((opt) => ( + { + onSortChange?.(opt.value); + setSortAnchor(null); + }} + sx={{ fontSize: '0.813rem' }} + > + {opt.label} + + ))} + + + + {/* Results count — below controls */} + + {providers.length} provider{providers.length !== 1 ? 's' : ''} found + {/* Provider list — click-to-navigate (D-D) */} diff --git a/src/components/pages/VenueStep/VenueStep.tsx b/src/components/pages/VenueStep/VenueStep.tsx index b28b8ce..ad41c7e 100644 --- a/src/components/pages/VenueStep/VenueStep.tsx +++ b/src/components/pages/VenueStep/VenueStep.tsx @@ -5,8 +5,10 @@ import InputAdornment from '@mui/material/InputAdornment'; import Autocomplete from '@mui/material/Autocomplete'; import FormControlLabel from '@mui/material/FormControlLabel'; import MenuItem from '@mui/material/MenuItem'; +import Menu from '@mui/material/Menu'; import ToggleButtonGroup from '@mui/material/ToggleButtonGroup'; import ToggleButton from '@mui/material/ToggleButton'; +import SwapVertIcon from '@mui/icons-material/SwapVert'; import ViewListOutlinedIcon from '@mui/icons-material/ViewListOutlined'; import MapOutlinedIcon from '@mui/icons-material/MapOutlined'; import LocationOnOutlinedIcon from '@mui/icons-material/LocationOnOutlined'; @@ -14,6 +16,7 @@ import type { SxProps, Theme } from '@mui/material/styles'; import { WizardLayout } from '../../templates/WizardLayout'; import { VenueCard } from '../../molecules/VenueCard'; import { FilterPanel } from '../../molecules/FilterPanel'; +import { Button } from '../../atoms/Button'; import { Chip } from '../../atoms/Chip'; import { Switch } from '../../atoms/Switch'; import { Typography } from '../../atoms/Typography'; @@ -210,6 +213,8 @@ export const VenueStep: React.FC = ({ runningTotal, sx, }) => { + const [sortAnchor, setSortAnchor] = React.useState(null); + const subheading = isPrePlanning ? 'Browse available venues. Your choice can be changed later.' : 'Choose a venue for the funeral service. You can filter by type, services, and tradition.'; @@ -310,46 +315,14 @@ export const VenueStep: React.FC = ({ sx={{ mb: 1.5 }} /> - {/* Control bar — results count, sort, view toggle, filters */} + {/* Control bar — view toggle, filters, sort on one line */} - {/* Results count — left */} - - {venues.length} venue{venues.length !== 1 ? 's' : ''} - {locationName ? ` near ${locationName}` : ''} found - - - {/* Sort */} - onSortChange?.(e.target.value as VenueSortBy)} - size="small" - aria-label="Sort venues" - sx={{ - minWidth: 160, - '& .MuiOutlinedInput-root': { fontSize: '0.813rem' }, - '& .MuiSelect-select': { py: '5px' }, - }} - > - {SORT_OPTIONS.map((opt) => ( - - {opt.label} - - ))} - - {/* View toggle */} = ({ aria-label="View mode" sx={{ '& .MuiToggleButton-root': { - px: 1, + px: 1.5, py: 0.5, + fontSize: '0.75rem', + fontWeight: 500, + gap: 0.5, border: '1px solid', borderColor: 'divider', + textTransform: 'none', '&.Mui-selected': { bgcolor: 'var(--fa-color-brand-100)', color: 'primary.main', @@ -373,10 +350,12 @@ export const VenueStep: React.FC = ({ }} > - + + List - + + Map @@ -493,7 +472,54 @@ export const VenueStep: React.FC = ({ /> + + {/* Sort — compact menu button, pushed right */} + + + setSortAnchor(null)} + anchorOrigin={{ vertical: 'bottom', horizontal: 'right' }} + transformOrigin={{ vertical: 'top', horizontal: 'right' }} + > + {SORT_OPTIONS.map((opt) => ( + { + onSortChange?.(opt.value); + setSortAnchor(null); + }} + sx={{ fontSize: '0.813rem' }} + > + {opt.label} + + ))} + + + + {/* Results count — below controls */} + + {venues.length} venue{venues.length !== 1 ? 's' : ''} + {locationName ? ` near ${locationName}` : ''} found + {/* Venue list — click-to-navigate */}