Batch 2: List-map layout rework — 420px fixed column, sticky headers

- WizardLayout ListMapLayout: 420px fixed left column (D-B), flex:1
  right panel, back link rendered inside left panel instead of above
  the split (eliminates gap above map)
- LAYOUT_MAP type updated to accept backLink prop for list-map variant
- ProvidersStep: heading + search + filters wrapped in sticky Box
  that pins at top of scrollable left panel while card list scrolls
- VenueStep: same sticky header treatment, heading moved inside form
  for consistent wrapper structure

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-29 22:18:52 +11:00
parent 6ebd52f36f
commit 1c3cdbc101
3 changed files with 134 additions and 94 deletions

View File

@@ -146,50 +146,62 @@ export const ProvidersStep: React.FC<ProvidersStepProps> = ({
)
}
>
{/* Header */}
<Typography variant="display3" component="h1" sx={{ mb: 0.5 }} tabIndex={-1}>
Choose a funeral provider
</Typography>
<Typography variant="body2" color="text.secondary" sx={{ mb: 3 }}>
{subheading}
</Typography>
{/* Search bar */}
<Box sx={{ mb: 2 }}>
<SearchBar
value={searchQuery}
onChange={onSearchChange}
onSearch={onSearch}
placeholder="Search providers..."
size="small"
/>
</Box>
{/* Filter chips */}
{filters && filters.length > 0 && (
<Box sx={{ display: 'flex', gap: 1, mb: 2, flexWrap: 'wrap' }}>
{filters.map((filter, index) => (
<Chip
key={filter.label}
label={filter.label}
selected={filter.active}
onClick={onFilterToggle ? () => onFilterToggle(index) : undefined}
variant="outlined"
size="small"
/>
))}
</Box>
)}
{/* Results count */}
<Typography
variant="caption"
color="text.secondary"
sx={{ mb: 2, display: 'block' }}
aria-live="polite"
{/* Sticky header — stays pinned while card list scrolls */}
<Box
sx={{
position: 'sticky',
top: 0,
zIndex: 1,
bgcolor: 'background.default',
pb: 1,
mx: -3,
px: 3,
}}
>
{providers.length} provider{providers.length !== 1 ? 's' : ''} found
</Typography>
<Typography variant="display3" component="h1" sx={{ mb: 0.5 }} tabIndex={-1}>
Choose a funeral provider
</Typography>
<Typography variant="body2" color="text.secondary" sx={{ mb: 3 }}>
{subheading}
</Typography>
{/* Search bar */}
<Box sx={{ mb: 2 }}>
<SearchBar
value={searchQuery}
onChange={onSearchChange}
onSearch={onSearch}
placeholder="Search providers..."
size="small"
/>
</Box>
{/* Filter chips */}
{filters && filters.length > 0 && (
<Box sx={{ display: 'flex', gap: 1, mb: 2, flexWrap: 'wrap' }}>
{filters.map((filter, index) => (
<Chip
key={filter.label}
label={filter.label}
selected={filter.active}
onClick={onFilterToggle ? () => onFilterToggle(index) : undefined}
variant="outlined"
size="small"
/>
))}
</Box>
)}
{/* Results count */}
<Typography
variant="caption"
color="text.secondary"
sx={{ mb: 0, display: 'block' }}
aria-live="polite"
>
{providers.length} provider{providers.length !== 1 ? 's' : ''} found
</Typography>
</Box>
{/* Error message */}
{error && (