Strip AI tooling and working docs for dev push
This commit is contained in:
@@ -1,122 +0,0 @@
|
||||
# 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 (two-line), name-only, price-only × verified, unverified × default, active | mapPin.paddingX/borderRadius/nub.size, color.brand.100-900, color.neutral.100-800 | Two-line label map marker: name (bold, truncated 180px) + "From $X" (centred, semibold). Name optional for price-only variant. Verified = brand palette, unverified = grey. Active inverts + scale. Pure CSS. role="button" + keyboard + focus ring. |
|
||||
| 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 | planned | Card + Typography + Badge | Compact horizontal map popup card. Deferred until map integration. |
|
||||
| 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 + Badge + Button + Divider + Typography + Tooltip + LocationOnOutlinedIcon + VerifiedOutlinedIcon + CheckCircleOutlineIcon + InfoOutlinedIcon | Mobile full-width package card for ComparisonPage tabpanels. Provider header (verified badge, name, location, rating, package name, price, CTA) + itemised sections with left-accent headings. Shadow (shadow-sm). Medium 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 verified badge, recommended banner, provider name (truncated+tooltip), location, rating, package name, price, CTA, optional Remove link. Extracted from ComparisonTable (2026-04-12). |
|
||||
| ComparisonTabCard | done | Card + Badge + Typography | Mobile tab rail card for ComparisonPage. Provider name + package name + price. Recommended badge in normal flow with negative margin overlap + brand glow. Fixed 210px width. Shared by V1 and V2 (extracted 2026-04-12). |
|
||||
|
||||
## 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 + Button + Badge + Link + Tooltip | Side-by-side package comparison CSS Grid. Sticky header cards with provider info + price + CTA. Row-merged sections (union of all items). 7 cell value types (discriminated union D036). Recommended column with warm bg + badge. Verified → "Make Arrangement", unverified → "Make Enquiry". ARIA table roles. Desktop only (mobile in ComparisonPage). Audit: 17/20. |
|
||||
| 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). |
|
||||
|
||||
## Templates
|
||||
|
||||
| Component | Status | Composed of | Notes |
|
||||
|-----------|--------|-------------|-------|
|
||||
| WizardLayout | done | Container + Box + Link + Typography + Navigation (slot) + StepIndicator (slot) | Page-level layout for arrangement wizard. 5 variants: centered-form, list-map, list-detail, grid-sidebar, detail-toggles. 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 + PackageDetail + Badge + TextField + Typography + Button | Wizard step 3 — package selection. List-detail split: compact provider + budget filter + package list w/ radiogroup (left), PackageDetail breakdown (right). "Most Popular" badge. Mobile Continue button. |
|
||||
| ~~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 (wide-form) + ComparisonTable + Card + Typography + Button + Divider + StarRoundedIcon | **Production version.** Package comparison page. Desktop: full ComparisonTable with sticky headers, **recommended package as first (leftmost) column**. Mobile: tabbed card view with horizontal tab rail (role="tablist") + single package card (role="tabpanel"); **recommended tab is first in rail, first user-selected package is initially active**. Recommended package as separate prop (D038). Star icon (brand-600) marks recommended in mobile tab labels. Share + Print in page header. 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~~ |
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,154 +0,0 @@
|
||||
# Component Lifecycle
|
||||
|
||||
Every component follows this lifecycle. Skills are run in order — each stage must
|
||||
pass before moving to the next. This prevents ad-hoc back-and-forth tweaking.
|
||||
|
||||
## The Stages
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ 1. BUILD /build-atom, /build-molecule, /build-organism │
|
||||
│ 2. STORIES /write-stories │
|
||||
│ 3. INTERNAL QA /audit → /critique → /harden │
|
||||
│ 4. FIX Fix all P0 and P1 issues from stage 3 │
|
||||
│ 5. POLISH /polish → /typeset → /adapt │
|
||||
│ 6. PRESENT Show to user in Storybook │
|
||||
│ 7. ITERATE User feedback → targeted fixes (1-2 rounds) │
|
||||
│ 8. NORMALIZE /normalize (cross-component consistency) │
|
||||
│ 9. PREFLIGHT /preflight │
|
||||
│ 10. COMMIT git add → commit → push │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## When to use each skill
|
||||
|
||||
### Stage 1 — BUILD
|
||||
**Skill:** `/build-atom`, `/build-molecule`, `/build-organism`
|
||||
**When:** Starting a new component. The skill handles reading memory files,
|
||||
checking the registry, creating the file structure, and writing the code.
|
||||
**Output:** Component .tsx + stories .tsx + index.ts
|
||||
|
||||
### Stage 2 — STORIES
|
||||
**Skill:** `/write-stories`
|
||||
**When:** If the build skill didn't produce comprehensive stories, or if stories
|
||||
need updating after changes. Stories must cover: default, all variants, all
|
||||
sizes, disabled, loading, error, long content, minimal content.
|
||||
**Output:** Complete story coverage in Storybook
|
||||
|
||||
### Stage 3 — INTERNAL QA (run before showing to user)
|
||||
Three skills, run in this order:
|
||||
|
||||
1. **`/audit`** — Technical quality (a11y, performance, theming, responsive, design).
|
||||
Produces a score out of 20 and P0-P3 issues.
|
||||
2. **`/critique`** — UX design review (hierarchy, emotion, cognitive load, composition).
|
||||
Produces a score out of 40 and priority issues.
|
||||
3. **`/harden`** — Edge cases (error states, empty states, loading, boundaries, disabled).
|
||||
Ensures robustness for real-world data.
|
||||
|
||||
**Exit criteria:** No P0 issues remaining. P1 issues documented.
|
||||
|
||||
### Stage 4 — FIX
|
||||
**No skill — just implementation work.**
|
||||
**When:** Fix all P0 and P1 issues found in stage 3.
|
||||
Then re-run the relevant check (e.g., if the fix was an a11y issue, re-run
|
||||
`/audit` to verify). Don't re-run all three unless the fixes were broad.
|
||||
**Exit criteria:** P0 = 0, P1 = 0 (or documented as intentional with rationale).
|
||||
|
||||
### Stage 5 — POLISH
|
||||
Three skills, run as needed based on the component:
|
||||
|
||||
1. **`/polish`** — Visual alignment, spacing, transitions, copy, micro-details.
|
||||
Run on every component.
|
||||
2. **`/typeset`** — Typography: hierarchy, line length, weight, readability.
|
||||
Run on text-heavy components (cards, forms, detail panels).
|
||||
3. **`/adapt`** — Responsive: touch targets, overflow, mobile spacing.
|
||||
Run on layout components (organisms, cards, navigation).
|
||||
|
||||
**Optional context-specific skills:**
|
||||
- **`/quieter`** — Run on components that handle sensitive moments (pricing,
|
||||
commitment steps, error messaging). Not needed for utility atoms.
|
||||
- **`/clarify`** — Run on components with decision points or complex information
|
||||
(FuneralFinder, ArrangementForm, PricingTable). Not needed for simple atoms.
|
||||
|
||||
### Stage 6 — PRESENT
|
||||
**No skill — show in Storybook.**
|
||||
**When:** All internal QA is done. The component should be in its best state
|
||||
before the user sees it. Present with a brief summary of what it does, key
|
||||
design decisions, and scores from audit/critique.
|
||||
|
||||
### Stage 7 — ITERATE
|
||||
**No skill — targeted fixes from user feedback.**
|
||||
**When:** User reviews in Storybook and gives feedback. This should be 1-2 rounds
|
||||
max because stages 3-5 caught most issues. If feedback requires major changes,
|
||||
go back to stage 1. Minor tweaks stay here.
|
||||
**Exit criteria:** User approves.
|
||||
|
||||
### Stage 8 — NORMALIZE
|
||||
**Skill:** `/normalize`
|
||||
**When:** After user approval, run against the component's tier (e.g., `/normalize atoms`)
|
||||
to check it's consistent with its peers. This catches: token access patterns (D031),
|
||||
transition timing, focus styles, spacing methods, displayName, exports.
|
||||
**Note:** This is a cross-component check, so it's most valuable after several
|
||||
components in a tier are done. Can be batched.
|
||||
|
||||
### Stage 9 — PREFLIGHT
|
||||
**Skill:** `/preflight`
|
||||
**When:** Before committing. Verifies TypeScript, Storybook build, token sync,
|
||||
hardcoded values, exports, ESLint, Prettier.
|
||||
**Exit criteria:** All critical checks pass.
|
||||
|
||||
### Stage 10 — COMMIT
|
||||
**No skill — git workflow.**
|
||||
Stage, commit with descriptive message, push. Husky runs lint-staged automatically.
|
||||
|
||||
---
|
||||
|
||||
## Shorthand for quick reference
|
||||
|
||||
| Stage | Skill(s) | Who triggers | Blocking? |
|
||||
|-------|----------|-------------|-----------|
|
||||
| Build | /build-{tier} | User requests | — |
|
||||
| Stories | /write-stories | Auto in build | — |
|
||||
| Internal QA | /audit → /critique → /harden | Agent (auto) | P0 = blocking |
|
||||
| Fix | — | Agent | Until P0/P1 = 0 |
|
||||
| Polish | /polish + /typeset + /adapt | Agent (auto) | — |
|
||||
| Present | — | Agent → User | — |
|
||||
| Iterate | — | User feedback | 1-2 rounds |
|
||||
| Normalize | /normalize | Agent (batch OK) | — |
|
||||
| Preflight | /preflight | Agent (auto) | Critical = blocking |
|
||||
| Commit | — | Agent | — |
|
||||
|
||||
**"Agent (auto)"** means I should run these proactively without being asked.
|
||||
**"Agent (batch OK)"** means it can be deferred and run across multiple components.
|
||||
|
||||
---
|
||||
|
||||
## Which skills are optional vs required?
|
||||
|
||||
| Skill | Required for | Optional for |
|
||||
|-------|-------------|-------------|
|
||||
| /audit | All components | — |
|
||||
| /critique | All molecules + organisms | Simple atoms (Button, Divider) |
|
||||
| /harden | All interactive components | Display-only atoms (Typography, Badge) |
|
||||
| /polish | All components | — |
|
||||
| /typeset | Text-heavy components | Icon-only or structural components |
|
||||
| /adapt | Layout components, organisms | Small inline atoms |
|
||||
| /quieter | Sensitive context components | Utility atoms |
|
||||
| /clarify | Decision-point components | Simple atoms |
|
||||
| /normalize | All (batched by tier) | — |
|
||||
| /preflight | All (before commit) | — |
|
||||
|
||||
---
|
||||
|
||||
## For existing components
|
||||
|
||||
Components built before this lifecycle was defined can be retroactively
|
||||
reviewed using a condensed process:
|
||||
|
||||
1. `/normalize {tier}` — Scan the tier for consistency issues
|
||||
2. `/audit {component}` — Score each component
|
||||
3. Fix P0/P1 issues only (don't re-polish what's already working)
|
||||
4. `/preflight` → commit
|
||||
|
||||
This is lighter than the full lifecycle because these components have already
|
||||
been through user review and iteration.
|
||||
@@ -1,203 +0,0 @@
|
||||
# FuneralFinder — Flow Logic Reference
|
||||
|
||||
Technical reference for the FuneralFinder stepped search widget.
|
||||
Use this when modifying the flow, adding steps, or integrating with a backend.
|
||||
|
||||
## Architecture Overview
|
||||
|
||||
The widget is a **single React component** with internal state. No external state
|
||||
management required. The parent only needs to provide `funeralTypes`, optional
|
||||
`themeOptions`, and an `onSearch` callback.
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────┐
|
||||
│ Header (h2 display + subheading) │
|
||||
│ ───────────────────────────────── │
|
||||
│ │
|
||||
│ CompletedRows (stack of answered steps)│
|
||||
│ │
|
||||
│ Active Step (one at a time, Collapse) │
|
||||
│ Step 1 │ Step 2 │ Step 3 │ Step 4 │
|
||||
│ │
|
||||
│ ─── always visible ─────────────────── │
|
||||
│ Location input │
|
||||
│ [Find funeral providers] CTA │
|
||||
│ Free to use · No obligation │
|
||||
└─────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## State
|
||||
|
||||
| State variable | Type | Default | Purpose |
|
||||
|---|---|---|---|
|
||||
| `intent` | `'arrange' \| 'preplan' \| null` | `null` | Step 1 answer |
|
||||
| `planningFor` | `'myself' \| 'someone-else' \| null` | `null` | Step 2 answer (preplan only) |
|
||||
| `typeSelection` | `string \| null` | `null` | Step 3 answer — funeral type ID or `'all'` |
|
||||
| `servicePref` | `'with-service' \| 'without-service' \| 'either'` | `'either'` | Step 4 answer |
|
||||
| `serviceAnswered` | `boolean` | `false` | Whether step 4 was explicitly answered |
|
||||
| `selectedThemes` | `string[]` | `[]` | Optional theme filter IDs (multi-select) |
|
||||
| `location` | `string` | `''` | Location input value |
|
||||
| `locationError` | `string` | `''` | Validation error for location |
|
||||
| `showIntentPrompt` | `boolean` | `false` | Show nudge when CTA clicked without intent |
|
||||
| `editingStep` | `number \| null` | `null` | Which step is being re-edited (via "Change") |
|
||||
|
||||
## Step Flow
|
||||
|
||||
### Active Step Calculation
|
||||
|
||||
```typescript
|
||||
const activeStep = (() => {
|
||||
if (editingStep !== null) return editingStep; // User clicked "Change"
|
||||
if (!intent) return 1; // Need intent
|
||||
if (needsPlanningFor && !planningFor) return 2; // Need planning-for (preplan only)
|
||||
if (!typeSelection) return 3; // Need funeral type
|
||||
if (showServiceStep && !serviceAnswered) return 4; // Need service pref
|
||||
return 0; // All complete
|
||||
})();
|
||||
```
|
||||
|
||||
`activeStep === 0` means all optional steps are answered. Only CompletedRows +
|
||||
location + CTA are visible.
|
||||
|
||||
### Step Details
|
||||
|
||||
| Step | Question | Options | Auto-advances? | Conditional? |
|
||||
|---|---|---|---|---|
|
||||
| 1 | How can we help you today? | Arrange now / Pre-plan | Yes, on click | Always shown |
|
||||
| 2 | Who are you planning for? | Myself / Someone else | Yes, on click | Only when `intent === 'preplan'` |
|
||||
| 3 | What type of funeral? | TypeCards + Explore All + theme chips | Yes, on type card click | Always shown |
|
||||
| 4 | Would you like a service? | With / No / Flexible (chips) | Yes, on chip click | Only when selected type has `hasServiceOption: true` |
|
||||
|
||||
### Auto-advance Mechanic
|
||||
|
||||
Steps 1, 2, and 4 auto-advance because selecting an option sets the state and
|
||||
clears `editingStep`. The `activeStep` recalculation on the next render
|
||||
determines the new step.
|
||||
|
||||
Step 3 also auto-advances when a type card is clicked. Theme preferences within
|
||||
step 3 are optional — they're captured at whatever state they're in when the
|
||||
type card click triggers collapse.
|
||||
|
||||
### Editing (reverting to a previous step)
|
||||
|
||||
Clicking "Change" on a CompletedRow calls `revertTo(stepNumber)`, which sets
|
||||
`editingStep`. This overrides the `activeStep` calculation, reopening that step.
|
||||
When the user makes a new selection, the handler clears `editingStep` and the
|
||||
flow recalculates.
|
||||
|
||||
**Key behaviour:** Editing a step does NOT reset downstream answers. If you
|
||||
change from Cremation to Burial (both have `hasServiceOption`), the service
|
||||
preference carries forward. If you change to a type without `hasServiceOption`
|
||||
(or to "Explore all"), `servicePref` resets to `'either'` and `serviceAnswered`
|
||||
resets to `false`.
|
||||
|
||||
## CTA and Search Logic
|
||||
|
||||
### Minimum Requirements
|
||||
|
||||
The CTA button is **always visible and always enabled** (except during loading).
|
||||
Minimum search requirements: **intent + location (3+ chars)**.
|
||||
|
||||
### Submit Behaviour
|
||||
|
||||
```
|
||||
User clicks "Find funeral providers"
|
||||
│
|
||||
├─ intent is null?
|
||||
│ → Show intent prompt (role="alert"), keep step 1 visible
|
||||
│ → Return (don't search)
|
||||
│
|
||||
├─ location < 3 chars?
|
||||
│ → Show error on location input
|
||||
│ → Return (don't search)
|
||||
│
|
||||
└─ Both present?
|
||||
→ Call onSearch() with smart defaults for missing optional fields
|
||||
```
|
||||
|
||||
### Smart Defaults
|
||||
|
||||
| Field | If not explicitly answered | Default value |
|
||||
|---|---|---|
|
||||
| `funeralTypeId` | User didn't select a type | `null` (= show all types) |
|
||||
| `servicePreference` | User didn't answer service step | `'either'` (= show all) |
|
||||
| `themes` | User didn't select any themes | `[]` (= no filter) |
|
||||
| `planningFor` | User on preplan path but didn't answer step 2 | `undefined` |
|
||||
|
||||
This means a user can: select intent → type location → click CTA. Everything
|
||||
else defaults to "show all."
|
||||
|
||||
### Search Params Shape
|
||||
|
||||
```typescript
|
||||
interface FuneralSearchParams {
|
||||
intent: 'arrange' | 'preplan';
|
||||
planningFor?: 'myself' | 'someone-else'; // Only on preplan path
|
||||
funeralTypeId: string | null; // null = all types
|
||||
servicePreference: 'with-service' | 'without-service' | 'either';
|
||||
themes: string[]; // May be empty
|
||||
location: string; // Trimmed, 3+ chars
|
||||
}
|
||||
```
|
||||
|
||||
## Conditional Logic Map
|
||||
|
||||
```
|
||||
intent === 'preplan'
|
||||
└─ Shows step 2 (planning-for)
|
||||
|
||||
typeSelection !== 'all' && selectedType.hasServiceOption === true
|
||||
└─ Shows step 4 (service preference)
|
||||
|
||||
typeSelection !== null
|
||||
└─ CompletedRow for type shows (with theme summary if any selected)
|
||||
|
||||
serviceAnswered && showServiceStep
|
||||
└─ CompletedRow for service shows
|
||||
|
||||
themeOptions.length > 0
|
||||
└─ Theme chips appear within step 3 (always, not gated by type selection)
|
||||
|
||||
loading === true
|
||||
└─ CTA button shows spinner, button disabled
|
||||
```
|
||||
|
||||
## Props Reference
|
||||
|
||||
| Prop | Type | Default | Notes |
|
||||
|---|---|---|---|
|
||||
| `funeralTypes` | `FuneralTypeOption[]` | required | Each has `id`, `label`, optional `description`, `note`, `hasServiceOption` |
|
||||
| `themeOptions` | `ThemeOption[]` | `[]` | Each has `id`, `label`. Shown as optional chips in step 3 |
|
||||
| `onSearch` | `(params: FuneralSearchParams) => void` | — | Called on valid submit |
|
||||
| `loading` | `boolean` | `false` | Shows spinner on CTA, disables button |
|
||||
| `heading` | `string` | `'Find funeral directors near you'` | Main h2 heading |
|
||||
| `subheading` | `string` | `'Tell us a little about...'` | Below heading |
|
||||
| `showExploreAll` | `boolean` | `true` | Show "Explore all options" TypeCard |
|
||||
| `sx` | `SxProps<Theme>` | — | MUI sx override on root card |
|
||||
|
||||
## Sub-components (internal)
|
||||
|
||||
| Component | Purpose | Used in |
|
||||
|---|---|---|
|
||||
| `StepHeading` | Centered bodyLg heading with bottom margin | Steps 1-4 |
|
||||
| `ChoiceCard` | Full-width radio card with label + description | Steps 1, 2 |
|
||||
| `TypeCard` | Compact radio card with label + optional description/note | Step 3 |
|
||||
| `CompletedRow` | Summary row: question + bold answer + "Change" link | All completed steps |
|
||||
|
||||
## Adding a New Step
|
||||
|
||||
1. Add state variable(s) for the new step's answer
|
||||
2. Add a condition in `activeStep` calculation (between existing steps)
|
||||
3. Add a `<Collapse in={activeStep === N}>` block in the render
|
||||
4. Add a `<Collapse>` for the CompletedRow (with appropriate visibility condition)
|
||||
5. Include the new data in `handleSubmit` → `onSearch()` params
|
||||
6. Update `FuneralSearchParams` type
|
||||
|
||||
## Known Limitations (deferred)
|
||||
|
||||
- **No progress indicator** — users can't see how many steps remain
|
||||
- **No roving tabindex** — radiogroups use button elements with `role="radio"` but
|
||||
arrow-key navigation between options is not implemented
|
||||
- **No location autocomplete** — free text input only, validated on length
|
||||
- **CSS vars used directly** — some styling uses `var(--fa-*)` tokens instead of
|
||||
MUI theme paths; works but doesn't support dynamic theme switching
|
||||
Reference in New Issue
Block a user