Batch 3: FilterPanel molecule + integration across 3 steps (D-C, D-F)

New molecule:
- FilterPanel: Popover-based reusable filter trigger with active
  count badge, Clear all, Done actions. D-C: Popover for MVP.

Step integrations:
- ProvidersStep: inline Chip filter bar → FilterPanel Popover,
  search bar + filter button side-by-side in sticky header
- VenueStep: same pattern, filter chips moved into Popover
- CoffinsStep (D-F): grid-sidebar layout → wide-form (full-width
  4-col grid), category + price selects moved into FilterPanel

WizardLayout:
- Added wide-form variant (maxWidth lg, single column) for
  card grids that benefit from full width
- wide-form included in STEPPER_VARIANTS for progress bar

Storybook:
- FilterPanel stories: Default, WithActiveFilters, SelectFilters,
  CustomLabel

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-29 22:24:54 +11:00
parent 1c3cdbc101
commit c5581c6e9f
8 changed files with 576 additions and 252 deletions

View File

@@ -9,6 +9,7 @@ import type { SxProps, Theme } from '@mui/material/styles';
import { WizardLayout } from '../../templates/WizardLayout';
import { VenueCard } from '../../molecules/VenueCard';
import { AddOnOption } from '../../molecules/AddOnOption';
import { FilterPanel } from '../../molecules/FilterPanel';
import { Collapse } from '../../atoms/Collapse';
import { Chip } from '../../atoms/Chip';
import { Typography } from '../../atoms/Typography';
@@ -81,6 +82,8 @@ export interface VenueStepProps {
services?: VenueService[];
/** Filter chip options */
filterOptions?: Array<{ key: string; label: string }>;
/** Callback to clear all filters */
onFilterClear?: () => void;
/** Location name for the results count */
locationName?: string;
/** Whether this is a pre-planning flow */
@@ -130,6 +133,7 @@ export const VenueStep: React.FC<VenueStepProps> = ({
{ key: 'features', label: 'Venue Features' },
{ key: 'religion', label: 'Religion' },
],
onFilterClear,
locationName,
isPrePlanning = false,
mapPanel,
@@ -224,8 +228,8 @@ export const VenueStep: React.FC<VenueStepProps> = ({
: 'Choose a venue for the funeral service. You can filter by location, features, and religion.'}
</Typography>
{/* ─── Search + Filters ─── */}
<Box sx={{ mb: 2 }}>
{/* ─── Search + Filter button ─── */}
<Box sx={{ display: 'flex', gap: 1, mb: 2, alignItems: 'flex-start' }}>
<TextField
placeholder="Search a town or suburb..."
value={values.search}
@@ -238,19 +242,19 @@ export const VenueStep: React.FC<VenueStepProps> = ({
</InputAdornment>
),
}}
sx={{ mb: 2 }}
/>
<Box sx={{ display: 'flex', gap: 1, flexWrap: 'wrap' }}>
{filterOptions.map((filter) => (
<Chip
key={filter.key}
label={filter.label}
onClick={() => handleFilterToggle(filter.key)}
selected={values.activeFilters.includes(filter.key)}
/>
))}
</Box>
<FilterPanel activeCount={values.activeFilters.length} onClear={onFilterClear}>
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 1 }}>
{filterOptions.map((filter) => (
<Chip
key={filter.key}
label={filter.label}
onClick={() => handleFilterToggle(filter.key)}
selected={values.activeFilters.includes(filter.key)}
/>
))}
</Box>
</FilterPanel>
</Box>
{/* ─── Results count ─── */}