Files
Parsons/docs/memory/component-registry.md
Richie e78d88b2f3 Add Google Maps ProviderMap organism with clustering + popup flow
Introduces a full Google-Maps-backed provider map for the arrangement
wizard's ProvidersStep. Clicking a pin morphs it into a MapPopup at
the same coord; pins within 70px of each other collapse into a cluster
(ceiling at zoom 13) that opens a ClusterPopup list on click. Row
clicks pan + zoom the map to the provider and open their MapPopup.
Map-background click routes through an exit transition that fades the
popup out before reappearing the pin, via a matching fade-in keyframe
on the atom markers.

Key additions:
- @vis.gl/react-google-maps + @googlemaps/markerclusterer deps
- ClusterMarker atom (count badge; verified / unverified palettes)
- ClusterPopup molecule (image-free rows; verified icon aligned to
  name; right-aligned "From $X" column; verified-first sort)
- ProviderMap organism (APIProvider + Map + imperative AdvancedMarker
  layer via createRoot for clusterer compatibility)

Component changes:
- MapPin: promoted verified palette (brand-700); name now required;
  name-only and price-only variants dropped; active prop removed in
  favour of organism-level state; SVG nub with fill+stroke replaces
  the CSS border-triangle trick so the outline is continuous
- MapPopup: `exiting` prop drives close animation; click events stop
  propagation so the map's onClick can't clear state mid-interaction
- ProviderData type gains optional `coords`; demo fixtures populated
  with real NSW/QLD lat/lng for all 7 providers
- ProvidersStep demo route wires ProviderMap into the mapPanel slot

Memory:
- docs/memory/component-registry updated (ClusterMarker, ClusterPopup,
  ProviderMap added; MapPin + MapPopup refined; MapCard retired)
- docs/memory/session-log captures arc across 2026-04-21/22 and flags
  next-session work: ProvidersStep polish, mobile layout for list-map
  WizardLayout, and demo deploy

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-22 09:29:37 +10:00

30 KiB
Raw Blame History

Component registry

Tracks the status, specification, and key details of every component in the design system. Agents MUST check this before building a component (to avoid duplicates) and MUST update it after completing one.

Status definitions

  • planned: Component is identified but not yet started
  • in-progress: Component is being built
  • review: Component is built, awaiting human review
  • done: Component is reviewed and approved
  • needs-revision: Component needs changes based on review feedback

Atoms

Component Status Variants Tokens used Notes
Button done contained, soft, outlined, text × xs, small, medium, large × primary, secondary + loading, underline, fullWidth button.height/paddingX/paddingY/fontSize/iconSize/iconGap/borderRadius, color.interactive.*, color.brand.100-300, color.neutral.200-700 Primary interactive element. Merges Text Button from Figma. Soft variant = Figma's Secondary/Brand & Secondary/Grey.
IconButton done default, primary, secondary, error × small, medium, large Reuses button.height/iconSize tokens, color.interactive., color.neutral. Icon-only button (close, menu, actions). Wraps MUI IconButton. Rounded rect, brand hover, focus ring.
Typography done displayHero, display1-3, displaySm, h1-h6, bodyLg, body1, body2, bodyXs, labelLg, label, labelSm, caption, captionSm, overline, overlineSm + maxLines, gutterBottom typography.* (all semantic typography tokens), fontFamily.body, fontFamily.display Text display system. Thin MUI wrapper with maxLines truncation.
Input done medium, small × default, hover, focus, error, success, disabled + startIcon, endIcon, required, multiline input.height/paddingX/paddingY/fontSize/borderRadius/gap/iconSize, color.neutral.300-400, color.brand.500, color.feedback.error/success, color.text.secondary External label pattern, branded focus ring, two sizes aligned with Button. Adds startIcon/endIcon and success state beyond Figma.
Badge done soft, filled × default, brand, success, warning, error, info × small, medium + icon badge.height/paddingX/fontSize/iconSize/iconGap/borderRadius, color.feedback.*, color.brand.200/700 Status indicator pill. Soft (tonal) or filled (solid). 6 colours, 2 sizes, optional leading icon.
Icon planned various sizes Icon wrapper component
Avatar planned image, initials, icon × small, medium, large User/entity representation
Divider done horizontal, vertical × fullWidth, inset, middle + text, flexItem color.border.default (via palette.divider) Visual separator. Wraps MUI Divider. Supports text children and orientation.
Chip done filled, outlined × small, medium × clickable, deletable, selected × default, primary chip.height/paddingX/fontSize/iconSize/deleteIconSize/iconGap/borderRadius, color.neutral.200-700, color.brand.200-700 Interactive tag. Wraps MUI Chip with FA tokens. Selected state promotes to brand colour. Filled uses soft tonal bg (like Badge).
Card done elevated, outlined × default, compact, none padding × interactive × selected card.borderRadius/padding/shadow/border/background, color.surface.raised/subtle/warm, color.border.default/brand, shadow.md/lg Content container. Elevated (shadow) or outlined (border). Interactive adds hover bg fill + shadow lift. Selected adds brand border + warm bg. Three padding presets.
Switch done bordered style × checked, unchecked, disabled switch.track.width/height/borderRadius, switch.thumb.size, color.interactive.*, color.neutral.400 Toggle for add-ons/options. Wraps MUI Switch. Bordered pill, brand.500 fill when active. From Parsons 1.0 Figma Style One.
Radio done checked, unchecked, disabled radio.size/dotSize, color.interactive.*, color.neutral.400 Single-select option. Wraps MUI Radio. Brand.500 fill when selected. From Parsons 1.0 Figma.
MapPin done name+price × verified, unverified mapPin.paddingX/borderRadius/nub.size, color.brand-200/700, color.neutral-100-800 Two-line label map marker: name (bold, required, truncated 180px) + "From $X" (centred, semibold). Verified = promoted brand palette (brand-700 bg, white text, brand-200 price). Unverified = neutral grey pill (neutral-100 bg, neutral-800 text). No active state — selection handled at the organism level (ProviderMap swaps pin → MapPopup on click). Pure CSS. role="button" + keyboard + focus ring. Name-only / price-only variants dropped in D042 (production providers always have both).
ClusterMarker done count × verified (promoted), unverified (neutral) color.brand-700, color.neutral-100-800, mapPin.nub.size Circular 36px count badge for pin clusters. hasVerified flag drives the palette (if any provider in the cluster is verified, use the promoted brand-700 palette; else neutral grey). Same nub treatment + shadow tokens as MapPin for visual cohesion. Pure CSS + SVG. role="button" + keyboard + focus ring. Designed as the render-ed output of @googlemaps/markerclusterer. See D043.
ColourToggle planned inactive, hover, active, locked × single, two-colour × desktop, mobile Circular colour swatch picker for products. Custom component. Deferred until product detail organisms.
Slider planned single, range × desktop, mobile Price range filter. Wraps MUI Slider. Deferred until search/filtering molecules.
Link done underline: hover/always/none × any MUI colour color.text.brand (copper brand.600, 4.8:1), color.interactive.active Navigation text link. Wraps MUI Link. Copper default, underline on hover, focus ring.
Collapse done in/out × unmountOnExit (none — uses MUI defaults) Progressive disclosure wrapper. Thin MUI Collapse wrapper with unmountOnExit default. Slide-down animation for wizard field reveal.
DialogShell done open/closed × with/without back button × with/without footer (theme defaults — borderRadius, palette) Standard dialog container. Header (title + optional back + close), divider, scrollable body, optional footer. Used by FilterPanel and ArrangementDialog.
ToggleButtonGroup done exclusive single-select × small, medium, large × error × fullWidth + descriptions color.neutral.100-200, color.brand.50/100, color.interactive.focus, color.feedback.error Button-select for binary/small-set choices. Fieldset/legend a11y, external label, helper/error text. Brand styling on selected.

Molecules

Component Status Composed of Notes
MiniCard done Card + Typography + Badge + Tooltip Compact vertical card for grids, recommendations, map popups. Image + title + optional price/badges/chips/meta (location, rating, capacity). Verified = icon-only circle badge in image. Hierarchy: title → meta → price → badges → chips. Truncated title shows tooltip. 3 component tokens. Audit: 20/20.
MapPopup done Paper + Typography + Tooltip Floating map popup anchored to MapPin. Clickable card (onClick). Image + name (1 line, tooltip) + meta + price. Verified = icon-only circle badge in image (matches MiniCard). Hierarchy matches MiniCard. Nub + drop-shadow. 260px wide.
FormField planned Input + Typography (label) + Typography (helper) Standard form field with label and validation
ProviderCard done Card + Typography + Badge + Tooltip Provider listing card. Verified: image + logo (64px rounded rect) + "Verified" badge. Unverified: text-only with top accent bar. Capability badges with info icon + tooltip. Price split typography. No footer. 4 component tokens.
VenueCard done Card + Typography Venue listing card. Always has photo + location + capacity ("X guests") + price ("From $X"). No verification tiers, no logo, no badges. 3 component tokens. Critique: 33/40.
MapCard superseded Retired 2026-04-21. Role (compact map popup card) fully covered by MapPopup. See D041.
ServiceOption done Card (interactive, selected) + Typography Selectable service option for arrangement flow. Heading + optional price (right-aligned) + optional description. role="radio" + aria-checked. Disabled state with opacity token. Maps to Figma ListItemPurchaseOption.
SearchBar done Input + IconButton + Button Search input with optional submit button. Enter-to-submit, progressive clear button, inline loading spinner. Guards empty submissions, refocuses after clear. role="search" landmark. Critique: 35/40.
AddOnOption done Card (interactive, selected) + Typography + Switch Toggleable add-on for arrangement flow extras. Heading + optional price + description + Switch. Click-anywhere toggle. Maps to Figma ListItemAddItem (2350:40658).
StepIndicator done Typography + Box Horizontal segmented progress bar. Brand gold for completed/current steps, grey for upcoming. Responsive bar height (10px/6px). Maps to Figma Progress Bar - Steps (2375:47468).
LineItem done Typography + Tooltip + InfoOutlinedIcon Name + optional info tooltip + optional price. Supports allowance asterisk, total variant (bold + top border). Font weight 500 (D019), prices text.secondary for readability hierarchy. Audit: 19/20.
ProviderCardCompact done Card (outlined) + Typography Horizontal compact provider card — image left, name + location + rating right. Used at top of Package Select page. Separate from vertical ProviderCard.
CartButton done Button + DialogShell + LineItem + Divider + Typography Outlined pill trigger: receipt icon + "Your Plan" + formatted total in brand colour. Click opens DialogShell with items grouped by section via LineItem, total row. Mobile: icon + price only. Lives in WizardLayout runningTotal slot.
CompareBar done Badge + Button + IconButton + Typography + Paper + Slide Floating comparison basket pill. Fixed bottom, slide-up/down. Package count badge + provider names + remove buttons + Compare CTA. Max 3 user packages. Disabled CTA when <2. Inline error for max-reached. Mobile: compact count + CTA only. Audit: 18/20.
ComparisonPackageCard done Card + Button + Divider + Typography + Tooltip + LocationOnOutlinedIcon + VerifiedOutlinedIcon + StarRoundedIcon + CheckCircleOutlineIcon + InfoOutlinedIcon Mobile full-width package card for ComparisonPage tabpanels. Provider header (inline VerifiedOutlinedIcon left of name when verified, name, location + rating, divider, package name, price block, full-width CTA) + itemised sections with left-accent headings. Warm tint confined to header only (not Card body) — Card is white (background.paper), header has surface-warm (recommended) or surface-subtle (verified) bg. 2px brand-600 border when recommended (matches desktop ComparisonColumnCard). Header px: 3, pt: 3, pb: 4. Package-info subgroup (name/label/price) in tight nested flex columns. Generous section spacing (mb: 5 between sections, py: 2 per item). Recommended banner at top. Shadow (shadow-sm). Medium full-width button. Reuses ComparisonPackage type from ComparisonTable. Shared by ComparisonPage V2 and V1 (extracted 2026-04-09).
ComparisonColumnCard done Card + Badge + Button + Divider + Typography + Tooltip + Link + StarRoundedIcon + VerifiedOutlinedIcon Desktop column header card for ComparisonTable. Floating badge: medium (26px) filled brand + StarRoundedIcon for recommended; soft brand + VerifiedOutlinedIcon for verified. Provider name wraps to 2 lines (WebkitLineClamp: 2) in a reserved 36px minHeight slot bottom-aligned so 1-line names anchor with location/rating/price at a consistent baseline. Recommended card: 2px brand-600 border + warm selected Card state + inline VerifiedOutlinedIcon left of name. pt: 5 (40px breathing above name), uniform regardless of verified/recommended. Remove link always renders as the same Link element (visibility-hidden when not applicable) so CTA+footer align across all cards. Per-column wrapper in ComparisonTable is display: flex with flex: 1 passed to the card root so all cards stretch to row height. Extracted from ComparisonTable (2026-04-12).
ComparisonTabCard done Card + Badge + Typography + StarRoundedIcon Mobile tab rail card for ComparisonPage. Provider name + package name + price. Recommended badge in normal flow with negative margin overlap — filled brand + StarRoundedIcon (matches desktop ComparisonColumnCard treatment, size="small" at 14px icon). Fixed 235px width (was 210). Border brand-600 when recommended (consistent with primary). No glow — uses standard shadow-sm like other cards. pt: 3.5 inside card. Shared by V1 and V2 (extracted 2026-04-12).
NearbyPackageCard done Card (outlined, interactive) + Typography + StarRoundedIcon + LocationOnOutlinedIcon Compact card representing a package offered by a nearby verified provider — package name + price + provider + rating + location. Used in the "Similar packages from verified providers nearby" section of PackagesStep for unverified tiers. Click is a route change to that verified provider's PackagesStep with this package loaded. Extracted from UnverifiedPackageT2/T3 during 2026-04-17 consolidation.
ClusterPopup done Paper + Typography + IconButton + ButtonBase + inline provider-rows (fixed verified-icon slot + name + location + rating) Cluster list popup — appears when a cluster marker is clicked. Header bar ("N providers in this area" + close X), scrollable stack of image-free provider rows (reserved verified-icon slot so titles align across tiers, name in copper for verified / neutral for unverified, location + rating meta). Verified-first sort order. 320px wide, matches MapPopup's card + nub + drop-shadow. Click on a row calls onSelectProvider(id); in the ProviderMap flow that pans+zooms the map to the provider's coords (zoom 15) and opens their single-provider popup — there's no back-to-list. See D043, D044.

Organisms

Component Status Composed of Notes
ServiceSelector done ServiceOption × n + Typography + Button Single-select service panel for arrangement flow. Heading + subheading + ServiceOption list (radiogroup) + optional continue Button. Manages selection state via selectedId/onSelect. maxDescriptionLines pass-through.
PricingTable planned PriceCard × n + Typography Comparative pricing display
PackageDetail done LineItem × n + Typography + Button + Divider Right-side package detail panel. Warm header band (surface.warm) with "Package" overline, name, price (brand colour), Make Arrangement + Compare (with loading) buttons. Sections: Essentials + Optionals (before total) + total + Extras (after total, with subtext). priceLabel pass-through to LineItem (D039). T&C grey footer. Audit: 19/20.
ComparisonTable done Typography + Card + Tooltip + ComparisonColumnCard Side-by-side package comparison. Fixed column widths (300px row-label + 300px per package, exported as COMPARISON_TABLE_COL_WIDTH). Natural width = 300 × (n+1). Sticky-left on row-label column across every per-section mini-table. Tiered hover: base cells → surface-subtle, recommended column cells → surface-warm (resting 50% opacity, promotes to full on row hover via color-mix). Per-section mini-tables with left-accent brand heading. "Not Included" rendering: unavailable cell values in Optionals/Extras sections render "Not Included" (neutral-500 weight 500); Essentials keeps em-dash. CellIconText local helper applies lineHeight: 1 to icon+text rows for optical centre alignment. ARIA table roles. Desktop only (mobile in ComparisonPage). Audit: 17/20 (pre-restructure).
FuneralFinder (V3) done Typography + Button + Divider + Select + MenuItem + OutlinedInput + custom StatusCard/SectionLabel Production version. Hero search widget — clean form with status cards. Standard card container (surface.raised, card shadow). "How Can We Help" section: two side-by-side StatusCards (Immediate Need default-selected / Pre-planning) — white bg, neutral border, brand border + warm bg when selected, stack on mobile. "Funeral Type" Select + "Location" OutlinedInput with pin icon — standard outlined fields, no focus ring (per design). Overline section labels (text.secondary). CTA "Find Funeral Directors →" always active — validates on click, scrolls to first missing field. Required: status + location. Funeral type defaults to "show all". Dividers after header and before CTA. WAI-ARIA roving tabindex on radiogroup. aria-labelledby via useId(). Critique: 33/40 (Good). Audit: 18/20 (Excellent).
FuneralFinder V1 archived Typography + Button + Chip + Input + Divider + Link + custom ChoiceCard/TypeCard/CompletedRow/StepHeading Archived — viewable in Storybook under Archive/. Stepped conversational flow. Audit: 14/20. Critique: 29/40.
FuneralFinder V2 archived Typography + Button + Input + Divider + Select + MenuItem + custom StepCircle Archived — viewable in Storybook under Archive/. Quick-form with step circles. Audit: 18/20. Critique: 33/40.
FuneralFinder V4 archived Typography + Button + Input + Divider + Select + MenuItem + custom StepIndicator/FieldError Archived. Based on V2 with: 3 numbered steps (48px circles, outline-to-fill + tick), ungated location field, no heading/subheading, "Search" CTA, inline copper error messages.
ArrangementForm planned StepIndicator + ServiceSelector + AddOnOption + Button + Typography Multi-step arrangement wizard. Deferred — build remaining atoms/molecules first.
Navigation done AppBar + Link + IconButton + Button + Divider + Drawer Responsive site header. Desktop: logo left, links right, optional CTA. Mobile: hamburger + drawer with nav items, CTA, help footer. Sticky, grey surface bg (surface.subtle). Real FA logo from brandassets/. Maps to Figma Main Nav (14:108) + Mobile Header (2391:41508).
Footer done Link × n + Typography + Divider + Container + Grid Light grey (surface.subtle) site footer — matches header. Logo + tagline + contact (phone/email) + link group columns + legal bar. Semantic HTML (footer, nav, ul). Critique: 38/40 (Excellent).
ProviderMap done MapPin + ClusterMarker + MapPopup + ClusterPopup + @vis.gl/react-google-maps + @googlemaps/markerclusterer Google Maps provider map with clustering. Individual pins: MapPin per provider — click morphs it into a MapPopup at the same coord. Clusters: pins within 70px of each other collapse into a ClusterMarker (count badge) only while zoomed out at level 13 or below — past that, every pin shows individually. Click a cluster → ClusterPopup list at the cluster centroid, verified-first. Click a row → map pans + zooms to that provider's coords (zoom 15) and opens their MapPopup; cluster state cleared (no back-to-list). Map-background click reverts to pins. Markers are rendered imperatively (via createRoot into AdvancedMarker content elements) so markerclusterer can group them; popup layer remains declarative React. selectedProviderId force-opens a popup for external selection. Subtle empty state when no API key or no providers have coords (no throw). API key read from VITE_GOOGLE_MAPS_API_KEY. Desktop-only for now; mobile map sheet deferred. See D041, D042, D043, D044.

Templates

Component Status Composed of Notes
WizardLayout done Container + Box + Link + Typography + Navigation (slot) + StepIndicator (slot) Page-level layout for arrangement wizard. 6 variants: centered-form, wide-form, list-map, list-detail, grid-sidebar, detail-toggles, bleed. bleed = viewport-locked + <main> as single scroll container (both axes) + no inner Container; back link routed into children; scroll host marked data-wizard-scroll so descendants can find it (IntersectionObserver roots, etc.). Used by ComparisonPage. Nav slot, sticky help bar, optional back link, optional progress stepper + running total. <main> landmark wrapper.

Pages

Component Status Composed of Notes
IntroStep done WizardLayout (centered-form) + ToggleButtonGroup × 2 + Collapse + Typography + Button + Divider Wizard step 1 — entry point. forWhom (Myself/Someone else) + hasPassedAway (Yes/No) with progressive disclosure. Auto-sets hasPassedAway="no" for "Myself". <form> wrapper, aria-live subheading, grief-sensitive copy. Pure presentation. Audit: 18/20 → 20/20 after fixes.
ProvidersStep done WizardLayout (list-map) + ProviderCard + SearchBar + Chip + Typography + Button Wizard step 2 — provider selection. List-map split: provider cards w/ radiogroup + search + filter chips (left), map slot (right). aria-live results count, back link. ProviderCard extended with HTML/ARIA passthrough. Audit: 18/20.
PackagesStep done WizardLayout (list-detail) + ProviderCardCompact + ServiceOption + NearbyPackageCard + PackageDetail + Divider + Link + Typography Wizard step 3 — package selection. Tier-aware unified page (replaces the old PackagesStep + UnverifiedPackageT2 + UnverifiedPackageT3 trio, 2026-04-17). providerTier: 'verified' | 'tier3' | 'tier2' drives heading, subhead, arrangeLabel, priceDisclaimer, and itemizedUnavailable via a TIER_COPY map. Discriminated secondaryList: same-provider-more (ServiceOption list, verified) or nearby-verified (NearbyPackageCard list, unverified). Same-provider-more shows top 3 inline; at >3 shows 3 + See all N packages from [Provider] → Link that fires onSeeAllPackages. showAllFromProvider prop renders a flat "All packages from [Provider]" variant (no grouping, no secondary list, preserves selectedPackageId). Primary list suppresses the "Matching your preferences" accent-bar heading when no secondary list is present (so the label only appears when there's something to contrast against). Desktop polished; mobile polish pending.
PreviewStep removed Replaced by ArrangementDialog organism (D-E). Package preview + "what's next" checklist now in the dialog's preview step.
AuthGateStep removed Replaced by ArrangementDialog organism (D-E). SSO/email auth flow now in the dialog's auth step.
DateTimeStep done WizardLayout (centered-form) + Input + TextField (date) + RadioGroup + Collapse + Divider + Button + Link Wizard step 6 — details & scheduling. Deceased name (Input atom, external label) + preferred dates (up to 3, progressive disclosure) + time-of-day radios. Service tradition removed (flows from provider/package). Dividers between sections. Grief-sensitive labels. Save-and-exit CTA.
VenueStep done WizardLayout (centered-form) + VenueCard + AddOnOption + Collapse + Chip + TextField + Divider + Button Wizard step 7a — venue browsing. Click-to-navigate card grid with search/filters. Leads to VenueDetailStep.
VenueDetailStep done WizardLayout (detail-toggles) + ImageGallery + Card + Chip + Typography + Button + Divider Wizard step 7b — venue detail. Two-panel: gallery/description/features/location (left), name/meta/price/CTA/religions (right). Informational service preview.
VenueServicesStep done WizardLayout (centered-form) + AddOnOption + Card + Typography + Button + Divider Wizard step 7c — venue services. Compact venue card, availability notices, AddOnOption toggles with "View more" for long descriptions. Follows VenueDetailStep.
CrematoriumStep done WizardLayout (centered-form) + Card + Badge + ToggleButtonGroup + Typography + Button + Divider Wizard step 8 — crematorium. Two variants: Service & Cremation (compact card + witness Yes/No toggle), Cremation Only (compact card + "Cremation Only" badge + "Included in Package" notice). Single pre-selected crematorium, no multi-select.
CemeteryStep done WizardLayout (centered-form) + ToggleButtonGroup + Collapse + TextField (select) + Typography + Button + Divider Wizard step 9 — cemetery. ToggleButtonGroups (Yes/No/Not sure) with progressive disclosure. Own plot → locate dropdown. No plot → preference? → select dropdown. No card grid.
CoffinsStep done WizardLayout (grid-sidebar) + Card + Badge + Collapse + Slider + TextField + Pagination + Divider + Link Wizard step 10 — coffin browsing. Grid-sidebar: filter sidebar (categories with expandable subcategories, dual-knob price slider with editable inputs, sort by) + 3-col card grid. CoffinCard with thumbnail hover preview. Equal-height cards, subtle bg for white-bg product photos. Card click → CoffinDetailsStep (no Continue). 20/page max. Conditional allowance info bubble.
CoffinDetailsStep done WizardLayout (detail-toggles) + ImageGallery + Divider + Button Wizard step 11 — coffin detail. Two-panel: gallery + product details dl (left), name + description + colour swatches + allowance-aware price + CTA (right). Allowance logic: fully covered / partially covered / no allowance. Colour selection does not affect price.
AdditionalServicesStep removed Replaced by IncludedServicesStep + ExtrasStep. Split for clearer distinction between free inclusions and paid extras.
IncludedServicesStep done WizardLayout (centered-form) + AddOnOption + RadioGroup + Collapse + Divider + Button Wizard step 12a — included services. Package inclusions at no additional cost: dressing, viewing (with same-venue sub-option), prayers/vigil, funeral announcement. Sub-options render inside parent card.
ExtrasStep done WizardLayout (centered-form) + AddOnOption + Card + Switch + RadioGroup + Collapse + Divider + Button Wizard step 12b — optional extras. Lead-gen interest capture: catering, music (inline live musician toggle + musician type), coffin bearing (toggle + bearer type), newspaper notice. POA via priceLabel. Tally of priced selections. No nested cards.
SummaryStep done WizardLayout (centered-form) + Card + Paper + DialogShell + Button + Link + Divider Wizard step 13 — plan review. Visual cart layout: arrangement details (2-col grid), compact cards with thumbnails for provider/venue/crematorium/coffin, checklist for included services, priced list for extras. Allowance display (fully covered vs remaining). Share dialog (multi-email). Location pin icons. Full-width CTA.
PaymentStep done WizardLayout (centered-form) + ToggleButtonGroup + Paper + Collapse + Checkbox + Divider + Button Wizard step 14 — payment. Plan (full/deposit) + method (card/bank). PayWay iframe slot. Bank transfer details. Terms checkbox.
ConfirmationStep done WizardLayout (centered-form) + Button Wizard step 15 — confirmation. Terminal page. At-need: "submitted" + callback. Pre-planning: "saved" + return-anytime. Muted success icon.
UnverifiedProviderStep done WizardLayout (list-detail) + ProviderCardCompact + ProviderCard + Badge + Button + Divider + Typography Unverified provider detail. Left: compact card + "Listing" badge + available info (conditional dl) + verified recommendations. Right: warm header band + detail rows + "Make an Enquiry" CTA. Graceful degradation (no data → straight to enquiry). 4 story variants.
HomePage done FuneralFinderV3/V4 (via finderSlot) + ProviderCardCompact + Button + Typography + Accordion + Divider + Navigation (prop) + Footer (prop) Marketing landing page. 4 archived versions: V1 (split hero), V2 (full-bleed parsonshero.png), V3 (hero-3.png + updated copy + logo bar + venue photos + warm CTA gradient), V4 (same as V3 but with FuneralFinderV4 stepped form via finderSlot). finderSlot prop allows swapping finder widget. Light grey footer (surface.subtle).
ComparisonPage (V2) done WizardLayout (bleed desktop / wide-form mobile) + ComparisonTable + ComparisonTabCard + ComparisonPackageCard + Divider + Typography + Button + Link Production version. Package comparison page, restructured 2026-04-17. Desktop: bleed WizardLayout variant. Structure: centred page-header container (maxWidth 1200 = COMPARISON_TABLE_COL_WIDTH × 4) with own Back link → <Divider> → full-bleed [spacer][ComparisonTable][spacer] flex row. When viewport > 1200 spacers centre the table; when a 4th+ package makes the table wider than viewport, spacers collapse to their min-width (16/24px matching the page-header padding) and the table extends rightward with the content's left edge pinned. Recommended package as first (leftmost) column with warm tint + 2px brand-600 border + filled Recommended badge. Mobile: <Divider> between page header and tab rail. "Choose a package to view" h2 heading (user-centric), serves as aria-labelledby for the tablist. Horizontal tab rail (role="tablist") of ComparisonTabCard (235px each) + dot indicator below (8px grey dots, active expands to 24×8 brand-600 pill, aria-hidden, tabIndex=-1 — visual supplement to the tab rail which is canonical accessible nav). Single ComparisonPackageCard in role="tabpanel"; recommended tab is first in rail, first user-selected package is initially active. Share + Print in page header (desktop). Back link, help bar.
ComparisonPage V1 archived WizardLayout + ComparisonTable + Card + Typography + Button + Divider Archived — viewable in Storybook under Archive/. Recommended package as last column/tab. Same component tree as V2.

Future enhancements

Deferred items that should be addressed when the relevant components or patterns are needed. Check this section before building new components — an item here may be relevant to your current work.

Item Relates to Trigger Notes
Destructive button colours Button When building delete/cancel flows color="error" already works via MUI palette. May need soft variant styling for error/warning/success colours.
Link-as-button Button When building Navigation or link-heavy pages Use MUI's component="a" or href prop. May warrant a separate Link atom or a Button story showing the pattern.
IconButton atom IconButton Resolved Built as atom. Rounded rect, 3 sizes, 4 colours, focus ring.
Google Fonts loading Typography Resolved Added to .storybook/preview-head.html and index.html