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:
@@ -146,7 +146,18 @@ export const ProvidersStep: React.FC<ProvidersStepProps> = ({
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
{/* Header */}
|
{/* 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,
|
||||||
|
}}
|
||||||
|
>
|
||||||
<Typography variant="display3" component="h1" sx={{ mb: 0.5 }} tabIndex={-1}>
|
<Typography variant="display3" component="h1" sx={{ mb: 0.5 }} tabIndex={-1}>
|
||||||
Choose a funeral provider
|
Choose a funeral provider
|
||||||
</Typography>
|
</Typography>
|
||||||
@@ -185,11 +196,12 @@ export const ProvidersStep: React.FC<ProvidersStepProps> = ({
|
|||||||
<Typography
|
<Typography
|
||||||
variant="caption"
|
variant="caption"
|
||||||
color="text.secondary"
|
color="text.secondary"
|
||||||
sx={{ mb: 2, display: 'block' }}
|
sx={{ mb: 0, display: 'block' }}
|
||||||
aria-live="polite"
|
aria-live="polite"
|
||||||
>
|
>
|
||||||
{providers.length} provider{providers.length !== 1 ? 's' : ''} found
|
{providers.length} provider{providers.length !== 1 ? 's' : ''} found
|
||||||
</Typography>
|
</Typography>
|
||||||
|
</Box>
|
||||||
|
|
||||||
{/* Error message */}
|
{/* Error message */}
|
||||||
{error && (
|
{error && (
|
||||||
|
|||||||
@@ -193,7 +193,27 @@ export const VenueStep: React.FC<VenueStepProps> = ({
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
{/* Page heading */}
|
<Box
|
||||||
|
component="form"
|
||||||
|
noValidate
|
||||||
|
aria-busy={loading}
|
||||||
|
onSubmit={(e: React.FormEvent) => {
|
||||||
|
e.preventDefault();
|
||||||
|
if (!loading) onContinue();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{/* 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,
|
||||||
|
}}
|
||||||
|
>
|
||||||
<Typography variant="display3" component="h1" sx={{ mb: 0.5 }} tabIndex={-1}>
|
<Typography variant="display3" component="h1" sx={{ mb: 0.5 }} tabIndex={-1}>
|
||||||
Where would you like the service?
|
Where would you like the service?
|
||||||
</Typography>
|
</Typography>
|
||||||
@@ -204,17 +224,8 @@ export const VenueStep: React.FC<VenueStepProps> = ({
|
|||||||
: 'Choose a venue for the funeral service. You can filter by location, features, and religion.'}
|
: 'Choose a venue for the funeral service. You can filter by location, features, and religion.'}
|
||||||
</Typography>
|
</Typography>
|
||||||
|
|
||||||
<Box
|
|
||||||
component="form"
|
|
||||||
noValidate
|
|
||||||
aria-busy={loading}
|
|
||||||
onSubmit={(e: React.FormEvent) => {
|
|
||||||
e.preventDefault();
|
|
||||||
if (!loading) onContinue();
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{/* ─── Search + Filters ─── */}
|
{/* ─── Search + Filters ─── */}
|
||||||
<Box sx={{ mb: 3 }}>
|
<Box sx={{ mb: 2 }}>
|
||||||
<TextField
|
<TextField
|
||||||
placeholder="Search a town or suburb..."
|
placeholder="Search a town or suburb..."
|
||||||
value={values.search}
|
value={values.search}
|
||||||
@@ -243,10 +254,11 @@ export const VenueStep: React.FC<VenueStepProps> = ({
|
|||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
{/* ─── Results count ─── */}
|
{/* ─── Results count ─── */}
|
||||||
<Typography variant="body2" color="text.secondary" sx={{ mb: 2 }} aria-live="polite">
|
<Typography variant="body2" color="text.secondary" sx={{ mb: 0 }} aria-live="polite">
|
||||||
Found {venues.length} venue{venues.length !== 1 ? 's' : ''}
|
Found {venues.length} venue{venues.length !== 1 ? 's' : ''}
|
||||||
{locationName ? ` near ${locationName}` : ''}
|
{locationName ? ` near ${locationName}` : ''}
|
||||||
</Typography>
|
</Typography>
|
||||||
|
</Box>
|
||||||
|
|
||||||
{/* ─── Venue card grid ─── */}
|
{/* ─── Venue card grid ─── */}
|
||||||
<Box
|
<Box
|
||||||
|
|||||||
@@ -142,11 +142,12 @@ const CenteredFormLayout: React.FC<{ children: React.ReactNode }> = ({ children
|
|||||||
</Container>
|
</Container>
|
||||||
);
|
);
|
||||||
|
|
||||||
/** List + Map: ~40% scrollable list (left) / ~60% map (right) */
|
/** List + Map: 420px fixed scrollable list (left) / flex map (right) — D-B */
|
||||||
const ListMapLayout: React.FC<{
|
const ListMapLayout: React.FC<{
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
secondaryPanel?: React.ReactNode;
|
secondaryPanel?: React.ReactNode;
|
||||||
}> = ({ children, secondaryPanel }) => (
|
backLink?: React.ReactNode;
|
||||||
|
}> = ({ children, secondaryPanel, backLink }) => (
|
||||||
<Box
|
<Box
|
||||||
sx={{
|
sx={{
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
@@ -156,18 +157,20 @@ const ListMapLayout: React.FC<{
|
|||||||
>
|
>
|
||||||
<Box
|
<Box
|
||||||
sx={{
|
sx={{
|
||||||
width: { xs: '100%', md: '40%' },
|
width: { xs: '100%', md: 420 },
|
||||||
|
flexShrink: 0,
|
||||||
overflowY: 'auto',
|
overflowY: 'auto',
|
||||||
px: { xs: 2, md: 3 },
|
px: { xs: 2, md: 3 },
|
||||||
py: 3,
|
py: 3,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
{backLink}
|
||||||
{children}
|
{children}
|
||||||
</Box>
|
</Box>
|
||||||
<Box
|
<Box
|
||||||
sx={{
|
sx={{
|
||||||
display: { xs: 'none', md: 'block' },
|
display: { xs: 'none', md: 'flex' },
|
||||||
width: '60%',
|
flex: 1,
|
||||||
position: 'relative',
|
position: 'relative',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
@@ -246,7 +249,11 @@ const DetailTogglesLayout: React.FC<{
|
|||||||
|
|
||||||
const LAYOUT_MAP: Record<
|
const LAYOUT_MAP: Record<
|
||||||
WizardLayoutVariant,
|
WizardLayoutVariant,
|
||||||
React.FC<{ children: React.ReactNode; secondaryPanel?: React.ReactNode }>
|
React.FC<{
|
||||||
|
children: React.ReactNode;
|
||||||
|
secondaryPanel?: React.ReactNode;
|
||||||
|
backLink?: React.ReactNode;
|
||||||
|
}>
|
||||||
> = {
|
> = {
|
||||||
'centered-form': CenteredFormLayout,
|
'centered-form': CenteredFormLayout,
|
||||||
'list-map': ListMapLayout,
|
'list-map': ListMapLayout,
|
||||||
@@ -313,8 +320,8 @@ export const WizardLayout = React.forwardRef<HTMLDivElement, WizardLayoutProps>(
|
|||||||
{/* Stepper + running total bar (grid-sidebar, detail-toggles only) */}
|
{/* Stepper + running total bar (grid-sidebar, detail-toggles only) */}
|
||||||
{showStepper && <StepperBar stepper={progressStepper} total={runningTotal} />}
|
{showStepper && <StepperBar stepper={progressStepper} total={runningTotal} />}
|
||||||
|
|
||||||
{/* Back link — inside a container for consistent alignment */}
|
{/* Back link — inside left panel for list-map, above content for others */}
|
||||||
{showBackLink && (
|
{showBackLink && variant !== 'list-map' && (
|
||||||
<Container
|
<Container
|
||||||
maxWidth={variant === 'centered-form' ? 'sm' : 'lg'}
|
maxWidth={variant === 'centered-form' ? 'sm' : 'lg'}
|
||||||
sx={{ pt: 2, px: { xs: 4, md: 3 } }}
|
sx={{ pt: 2, px: { xs: 4, md: 3 } }}
|
||||||
@@ -325,7 +332,16 @@ export const WizardLayout = React.forwardRef<HTMLDivElement, WizardLayoutProps>(
|
|||||||
|
|
||||||
{/* Main content area */}
|
{/* Main content area */}
|
||||||
<Box component="main" sx={{ display: 'flex', flexDirection: 'column', flex: 1 }}>
|
<Box component="main" sx={{ display: 'flex', flexDirection: 'column', flex: 1 }}>
|
||||||
<LayoutComponent secondaryPanel={secondaryPanel}>{children}</LayoutComponent>
|
<LayoutComponent
|
||||||
|
secondaryPanel={secondaryPanel}
|
||||||
|
backLink={
|
||||||
|
showBackLink && variant === 'list-map' ? (
|
||||||
|
<BackLink label={backLabel} onClick={onBack} />
|
||||||
|
) : undefined
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</LayoutComponent>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
{/* Sticky help bar */}
|
{/* Sticky help bar */}
|
||||||
|
|||||||
Reference in New Issue
Block a user