Phase 1: Session log archived (1096→91 lines), D031 token access convention
Phase 2: ESLint v9 + Prettier + jsx-a11y, initial config and lint fixes
Phase 3: 7 new skills (polish, harden, normalize, clarify, typeset, quieter, adapt)
+ Vercel reference docs, updated audit/review-component refs
Phase 4: Husky + lint-staged pre-commit hooks, preflight updated to 8 checks
Phase 5: Vitest + Testing Library + /write-tests skill
- Badge.tsx colour maps unified to CSS variables (D031)
- 5 empty interface→type alias fixes (Switch, Radio, Divider, IconButton, Link)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
63 KiB
Session 2026-03-26d — FuneralFinder v2 build
Agent(s): Claude Opus 4.6 (1M context)
Work completed:
- Built FuneralFinderV2 from scratch — completely different approach from v1 (quick-form vs stepped wizard)
- 4-step vertical form with 48px numbered circles (brand-200 default → brand-500 completed) and 3px connector lines
- Steps: (1) Intent (3 options), (2) Planning for (conditional auto-set for arrange-now), (3) Funeral type (5 options), (4) Location
- Sequential unlock logic: each step enables only when the previous is filled
- Labels use brand-700 copper when active, text.disabled when locked
- Selects match Input medium height (48px) via py: 14px
- Display serif heading + body2 subheading with full-width divider
- Default contained CTA (copper), disabled until location has 3+ chars
- Trust signal "Free to use · No obligation" below CTA
- Focus rings suppressed (subtle brand-400 border only)
- Full accessibility: role="search", aria-required, aria-label on all fields
- Multiple iteration rounds incorporating user feedback on sizing, alignment, colours, spacing, and layout
- Ran /critique (33/40 Good) and /audit (18/20 Excellent) — fixed all P0/P1 issues
Decisions made:
- v2 keeps v1 alongside — both exported from index.ts for comparison
- Step circles use brand-200 warm fill (not neutral grey) for palette cohesion
- "Plan a funeral for someone expected to pass soon" softened to "Plan ahead for someone who is unwell"
- Connector lines use ::after on each StepCircle rather than container ::before (starts from circle bottom, not above)
- Location input uses no icon, matches select styling (py: 14px, fontSize: 0.875rem)
Open questions:
- Which version (v1 or v2) to proceed with for production? May keep both and A/B test
- Connector line height (60px) is a magic number — works for single-line labels but would need adjustment if labels wrap
Next steps:
- User to review in Storybook and decide on v1 vs v2 direction
- If v2 chosen: add location autocomplete, consider progress summary state
- Update docs/reference/ with v2 flow logic doc (similar to funeral-finder-logic.md for v1)
Session 2026-03-26c — FuneralFinder v1 refinement and completion
Agent(s): Claude Opus 4.6 (1M context)
Work completed:
- Redesigned FuneralFinder from a "dump everything in step 3" pattern to a full stepped conversational flow
- Every decision is now its own step with CompletedRow collapse (intent → planning-for → type+preferences → service → location+CTA)
- CTA ("Find funeral providers") and location input are always visible at the bottom — not gated behind steps
- Implemented smart defaults: minimum search requirements are intent + location; type/service/themes default to "show all"
- Added funeral type options: Cremation, Burial, Water Burial (QLD only), Explore All (as a proper TypeCard)
- Added service preference step (conditional): With a service / No service / I'm flexible
- Added theme preferences (eco-friendly, budget-friendly, religious specialisation) as optional sub-option within type step
- Created StepHeading sub-component (bodyLg, centered) for clear hierarchy vs card labels (body1/body2)
- Added loading prop for CTA button, location validation (3+ chars with error state)
- Added Divider under subheading, h2 display heading, generous CompletedRow spacing (py: 1.5)
- Fixed accessibility: aria-label on Change links, role="alert" on intent prompt, 44px touch targets on all chips
- Removed "Take your time" empathetic message per user preference
- Renamed "ceremony" → "service" throughout, "Without (direct)" → "No service"
- Removed TypeCard descriptions for standard types (Cremation, Burial don't need them)
- Multiple audit/critique cycles: final scores Audit 14/20 (Good), Critique 29/40 (Good)
Decisions made:
- CTA always visible with smart defaults — users can skip optional steps and search with just intent + location
- Stepped flow continues through ALL decisions (not just steps 1-2 like the previous version)
- Theme preferences belong in the type step as a sub-option, not in the location step
- "Where are you looking?" (not "located") to allow searching outside own area
- Step headings use bodyLg centered for visual hierarchy distinct from card labels
Open questions:
- Progress indicator (Step X of Y) — flagged by critique as P2, deferred. Variable step count makes implementation non-trivial.
- Roving tabindex for radiogroups — flagged by audit as P0, deferred. Requires arrow-key handler + tabindex management.
- Location autocomplete — flagged by critique as P2, deferred. Would need suburb/postcode API integration.
- CSS var vs MUI theme accessor consistency — flagged by audit, deferred. Architectural choice to address system-wide.
Next steps:
- FuneralFinder v1 is complete and approved
- Consider building the homepage hero composition as a standalone organism or page template
- ArrangementForm organism is next planned organism (multi-step wizard with StepIndicator)
Session 2026-03-24 — Project scaffold setup and hygiene
Agent(s): Manual (no agents invoked — setup phase)
Work completed:
- Fixed missing
.storybook/directory (main.ts + preview.tsx with MUI ThemeProvider) - Created
.gitignore(was missing entirely) - Created
.mcp.jsonwith Figma remote MCP config - Removed malformed
{.claude/agents,.claude/...}directory tree (bash brace expansion bug) - Created 3 agent definitions: token-architect, component-builder, story-writer
- Created 8 slash commands: create-tokens, build-atom, build-molecule, build-organism, write-stories, sync-tokens, status, review-component
- Migrated commands from
.claude/commands/to.claude/skills/<name>/SKILL.mdformat with YAML frontmatter - Fixed critical Style Dictionary v4 config: converted from CommonJS to ESM (
StyleDictionaryclass API) - Changed
build:tokensscript fromstyle-dictionary build --config ...tonode style-dictionary/config.js - Added
"type": "module"to package.json for ESM support - Changed SD output from
tokens.tstotokens.js(Style Dictionary v4 generates JS, not TS) - Registered
@storybook/addon-designsin.storybook/main.ts(was installed but not configured) - Added CSS token import to
.storybook/preview.tsx - Added Card and Link to CLAUDE.md atom list (were missing)
- Fixed broken Penpot/Storybook MCP references in
docs/reference/mcp-setup.md - Improved agent instructions with pre-flight dependency checks, story checklist enforcement, token validation steps, and MUI theme mapping guide
- Created
src/components/{atoms,molecules,organisms}/directories - Fixed
bootstrap.shto check for.storybook/dir instead ofnode_modules/@storybook - Verified
npm run build:tokensruns successfully (empty output expected — no tokens yet) - Verified Storybook runs at http://localhost:6006
Decisions made:
- Skills use
.claude/skills/<name>/SKILL.mdformat (not.claude/commands/) - Style Dictionary v4 config is a standalone ESM script run via
node, not CLI - British spelling for filenames (
colours.json), standardcolornamespace for token paths
Open questions:
- Slash commands
/create-tokensetc. showing "Unknown skill" — may need Claude Code restart to discover newly created skills. User should test after restarting.
Next steps:
Verify slash commands work after Claude Code restart✓ Skills workingBegin Step 1:✓ Done/create-tokenswith brand colours, fonts, and reference material
Session 2025-03-25 — Token creation (Step 1)
Agent(s): token-architect (via /create-tokens skill)
Work completed:
- Extracted brand colours from user-provided swatch image (12 colours across 3 palettes)
- Reviewed 5 Parsons FA 1.0 Figma screens for colour application context
- Reviewed 2 FA 2.0 Design System Template screens (buttons + inputs)
- Created complete primitive tokens:
- Colour scales (50-950): brand (warm gold), sage (cool grey-green), neutral, red, amber, green, blue + white/black
- Typography: 3 font families (Montserrat, Noto Serif SC, JetBrains Mono), font size scale (xs-4xl + mobile), weights, line heights, letter spacing
- Spacing: 4px-based scale (2px-80px), border radius scale
- Effects: 4 shadow levels, 3 opacity values
- Created complete semantic tokens:
- Colour mappings: text (9 variants), surface (6), border (6), interactive (7), feedback (8)
- Typography roles: display, h1-h4, bodyLarge, body, bodySmall, caption, label, overline — each with font family, size, weight, line height, letter spacing + mobile size overrides
- Spacing: component (xs-lg), layout (gutter, section, page, padding) with mobile/desktop variants
- Fixed Style Dictionary v4.4.0 CSS output: added
usesDtcg: trueflag (required for DTCG format CSS generation) - Generated outputs:
- CSS: 245 custom properties in
src/theme/generated/tokens.csswithvar()references for semantic tokens - JS: 258 named exports in
src/theme/generated/tokens.js - JSON: flat export in
tokens/export/tokens-flat.json
- CSS: 245 custom properties in
- Updated MUI theme (
src/theme/index.ts):- All palette colours mapped from token imports
- All typography variants mapped (h1-h6, body1, body2, subtitle1/2, caption, overline, button)
- 3 custom typography variants added: display, bodyLarge, label (with TS module declarations)
- Responsive font sizes via @media queries for display, h1, h2, h3
- Component overrides for Button and Card border radius
- Updated docs/design-system.md with actual brand colours, palettes, and font stacks
- Updated docs/memory/decisions-log.md with 8 design decisions (D001-D008)
- Updated docs/memory/token-registry.md with complete token reference
Decisions made:
- D001: Primary brand colour is #BA834E (warm gold from swatch)
- D002: Primary text colour is #2C2E35 (charcoal, not pure black)
- D003: Brand link colour uses #B0610F (copper, meets WCAG AA)
- D004: Sage palette as secondary (calming contrast to warm primary)
- D005: Noto Serif SC for display/H1-H2, Montserrat for H3+ and body
- D006: Warning text uses amber.700 for AA compliance
- D007: Style Dictionary requires usesDtcg: true for CSS output
- D008: Responsive typography via explicit @media queries in MUI theme
Open questions:
- Font name confirmation: user wrote "Not Serif SC" — interpreted as "Noto Serif SC" (Google Font). Needs confirmation.
- brand.500 (#BA834E) has 3.7:1 contrast on white — AA for large text only. Primary buttons use white text on this background, which works for button-sized text. Should we darken the primary CTA colour for better accessibility, or is the current value acceptable?
- Token collision warning: benign collision on
$type: "color"set in both primitives and semantic colour files. Doesn't affect output.
Next steps:
Confirm display font name (Noto Serif SC vs something else)Begin Step 2: Build first atom component (Button recommended as it exercises the most tokens)✓ Done- Consider adding Google Fonts import for Montserrat and Noto Serif SC to index.html or Storybook preview
Session 2026-03-25 — Button atom (Step 2)
Agent(s): Claude Opus (via conversation)
Work completed:
- Reviewed 3 Figma component sets: Icons (29:54), Button (28:50), Text Button (32:1361)
- Created button component tokens (
tokens/component/button.json): height, paddingX, paddingY, fontSize, iconSize, iconGap, borderRadius for xs/sm/md/lg sizes - Rebuilt token pipeline — 25 new button tokens generated across CSS/JS/JSON outputs
- Updated MUI theme (
src/theme/index.ts) with comprehensive MuiButton overrides:- 4 sizes: xs (28px), small (32px), medium (40px), large (48px)
- Contained, outlined, text variants for primary and secondary colours
- Hover backgrounds using brand.100 and sage.100 for outlined/text variants
- Focus-visible outline (2px solid interactive.focus, 2px offset)
- Disabled elevation via
disableElevation: truedefault prop - Custom
xssize via MUI variant system + module augmentation
- Created Button component (
src/components/atoms/Button/Button.tsx):- Wraps MUI Button with React.forwardRef
- Custom props:
loading(spinner + disabled),underline(text-decoration for text variant) - Accepts all MUI ButtonProps (variant, color, size, startIcon, endIcon, fullWidth, etc.)
- Created barrel export (
src/components/atoms/Button/index.ts) - Created comprehensive Storybook stories (
Button.stories.tsx): 16 stories covering Default, Variants (primary/secondary), AllSizes, Icons, Disabled, Loading, TextWithUnderline, FullWidth, LongContent, CompleteMatrix - Storybook builds successfully with Button stories
Decisions made:
- D009: Merge Text Button into Button atom — text buttons are
variant="text"with optionalunderlineprop, not a separate component - D010: Button sizes adjusted for touch targets — xs: 28px, sm: 32px, md: 40px, lg: 48px (lg meets 44px minimum)
- D011: Use
@mui/icons-materialover Font Awesome — native MUI integration, no adapter needed, tree-shakeable - D012: Responsive sizing is a composition concern — Button size is an explicit prop, not responsive by default. Layouts choose the right size per breakpoint.
Open questions:
- primary.main maps to brand.600 (copper #B0610F) for AA compliance, but Figma designs show brand.500 (warm gold #BA834E) as primary button fill. Should we adjust? Current mapping prioritises accessibility.
- Google Fonts import still needed for Montserrat and Noto Serif SC in Storybook
- Icon approach confirmed as @mui/icons-material — should we create any custom SvgIcon components for FA-specific icons?
Next steps:
User to review Button in Storybook and provide feedback on colours/sizing✓ Feedback received- Build Typography atom
- Add Google Fonts to Storybook preview
Log D009-D012 in decisions-log.md✓ Done
Session 2026-03-25b — Button refinements from user review
Agent(s): Claude Opus (via conversation)
Work completed:
- Fetched Figma Secondary/Brand and Secondary/Grey button details — discovered they are soft-filled (tonal) buttons, not outlined
- Added custom
variant="soft"to MUI Button — tonal/muted fill treatment- Primary soft: brand.200 bg (#EBDAC8), brand.700 text (#8B4E0D), brand.300 hover
- Secondary soft: neutral.200 bg (#E8E8E8), neutral.700 text (#404040), neutral.300 hover
- Changed MUI secondary palette from sage to neutral grey (neutral.600 main, neutral.700 dark, neutral.300 light)
- Updated all secondary button overrides (outlined, text) from sage to neutral
- Moved loading spinner from left to right side of button text
- Updated stories: added FigmaMapping story, soft variant stories, LoadingToSuccess pattern story
- Logged D013-D015 in decisions log
Decisions made:
- D013: Added
softvariant for tonal buttons — maps to Figma Secondary/Brand and Secondary/Grey - D014: Secondary palette changed from sage to neutral grey
- D015: Loading spinner positioned on right
Open questions:
- primary.main maps to brand.600 (copper #B0610F) for AA compliance, but Figma designs show brand.500 (warm gold #BA834E) as primary button fill. Should we adjust?
- Google Fonts import still needed for Montserrat and Noto Serif SC in Storybook
- Icon approach confirmed as @mui/icons-material — should we create any custom SvgIcon components for FA-specific icons?
- Sage palette no longer used for buttons — consider if it should be re-introduced as a custom colour later
Next steps:
User to re-review Button in Storybook✓ Approved as good baselineBuild Typography atom✓ DoneAdd Google Fonts to Storybook preview✓ Done
Session 2026-03-25c — Typography atom + housekeeping
Agent(s): Claude Opus (via conversation)
Work completed:
- Added Google Fonts loading: Montserrat (400/500/600/700) + Noto Serif SC (600/700) in
.storybook/preview-head.htmlandindex.html - Created Typography component (
src/components/atoms/Typography/Typography.tsx):- Thin wrapper around MUI Typography with React.forwardRef
- Custom prop:
maxLinesfor CSS line-clamp truncation - All MUI Typography props passed through (variant, color, align, component, gutterBottom, etc.)
- Created barrel export (
src/components/atoms/Typography/index.ts) - Created comprehensive Storybook stories (9 stories): Default, HeadingHierarchy, BodyVariants, UIText, Colours, SemanticHTML, MaxLines, RealisticContent, FontFamilies
- Added "Future enhancements" tracking table to component-registry.md — deferred items (IconButton, destructive colours, link-as-button) tracked with triggers for when to address them
- Logged D016 (primary colour confirmed as copper brand.600) in decisions-log.md
- Storybook builds successfully
Decisions made:
- D016: Primary button colour confirmed as copper (brand.600) — user approved
- Typography atom is a thin wrapper + maxLines — no over-engineering
Open questions:
- Icon approach confirmed as @mui/icons-material — should we create any custom SvgIcon components for FA-specific icons?
- Sage palette no longer used for buttons — consider if it should be re-introduced as a custom colour later
Next steps:
- User to review Typography in Storybook
- Build next atom (Input or Card recommended — Input for forms, Card for service listings)
- Consider building FormField molecule next if Input is done (label + input + helper text)
Session 2026-03-25d — Typography expansion (21 variants)
Agent(s): Claude Opus (via conversation)
Work completed:
- Reviewed user's FA 2.0 Figma type scale (node 23:30) — 21 variants across 6 categories, 3 responsive breakpoints
- Expanded primitive typography tokens: added fontSize.2xs (11px), fontSize.display.* sub-group (hero 80px through sm 32px), mobile overrides for all display and heading sizes
- Rewrote semantic typography tokens: 21 variants with specific line-heights and letter-spacing per variant
- Rewrote MUI theme typography section: refactored to wildcard import (
import * as t), added all 21 variants with module augmentations, responsive scaling via @media queries - Updated Google Fonts: added Noto Serif SC weight 400 (Regular) for display text
- Updated Typography component JSDoc with full variant guide
- Rewrote Typography stories: 10 stories including CompleteScale (all 21 variants matching Figma layout)
- Key font changes: headings now Montserrat Bold (not serif), display now Regular 400 (not Bold), body now Medium 500 (not Regular)
Decisions made:
- D017: Headings use Montserrat Bold, not Noto Serif SC (supersedes D005)
- D018: Display weight is Regular 400, not Bold
- D019: Body weight is Medium 500 (user preference, 450 not available)
- D020: 21 typography variants across 6 categories
Next steps:
User to review expanded type scale in Storybook✓- Fine-tune heading sizes if they don't match Figma exactly (h2-h6 were estimated)
Build next atom (Input or Card)✓ Input done
Session 2026-03-25e — Input atom
Agent(s): Claude Opus (via conversation)
Work completed:
- Reviewed FA 2.0 Figma Input Field design (node 39:713) — 9 states × 4 toggle properties = ~90 variants
- Analysed Figma design and provided feedback: identified 7 improvements (leading icons, size variation, required indicator, select vs input naming, multiline, character count, error icon treatment)
- Created Input component tokens (
tokens/component/input.json): height (sm/md), paddingX, paddingY (sm/md), fontSize, borderRadius, gap, iconSize — 9 tokens total - Rebuilt token pipeline — 9 new input tokens generated across CSS/JS/JSON outputs
- Updated MUI theme (
src/theme/index.ts) with comprehensive MuiOutlinedInput overrides:- Border colours per state: neutral.300 default, neutral.400 hover, brand.500 focus, error/success for validation
- Focus ring: double box-shadow (2px white gap + 4px brand.500) matching Figma's elevation-special/focus-ring effect
- Error + focus ring: error-coloured ring
- Disabled background: neutral.100
- Two sizes via minHeight: medium (48px), small (40px)
- Icon sizing: 20px via InputAdornment
- Notch legend hidden for external label pattern
- Multiline padding normalisation
- Created Input component (
src/components/atoms/Input/Input.tsx):- Composes FormControl + InputLabel + OutlinedInput + FormHelperText
- External label pattern (InputLabel with position:static, no floating)
- Custom props:
label,helperText,success,startIcon,endIcon,fullWidth - Label stays neutral on error/focus/success (per Figma design)
- Required asterisk on label (via MUI InputLabel)
- Success state: green border + green helper text (not a native MUI state)
- Error helper text has
role="alert"for screen readers aria-describedbyconnection between input and helper text- Supports multiline via
multiline+rows/minRows/maxRows
- Created barrel export (
src/components/atoms/Input/index.ts) - Created comprehensive Storybook stories (11 stories): Default, FigmaMapping, AllStates, Required, Sizes, SizeAlignment, WithIcons, PasswordToggle, Multiline, ValidationFlow, ArrangementForm, CompleteMatrix
- Logged D021-D025 in decisions log
- Updated component registry (Input → review)
- Storybook builds successfully
Decisions made:
- D021: External label pattern, not MUI floating label
- D022: Two sizes — medium 48px (matches Button large), small 40px (matches Button medium)
- D023: Focus ring uses brand.500 warm gold (Figma spec), not brand.600
- D024: Label stays neutral on error/success (calmer for FA audience)
- D025: Added startIcon/endIcon convenience props and success validation state
Open questions:
- Should error+focus ring be error-coloured or brand-coloured? Currently error-coloured (reinforces the validation state during keyboard navigation)
- FormField molecule may now be unnecessary — Input already includes label + helper text. Consider repurposing FormField as a layout/validation wrapper instead.
- Should we add a character count feature? (Useful for textarea fields like special instructions)
Next steps:
User to review Input in Storybook✓Build next atom (Card, Badge, or Chip recommended)✓ Card done- Consider whether FormField molecule is still needed given Input's built-in label/helperText
Session 2026-03-25f — Card atom
Agent(s): Claude Opus (via conversation)
Work completed:
- Created card component tokens (
tokens/component/card.json): borderRadius, padding (default 24px / compact 16px), shadow (default md / hover lg), border, background — 7 tokens total - Rebuilt token pipeline — 7 new card tokens generated across CSS/JS/JSON outputs
- Updated MUI theme (
src/theme/index.ts) with MuiCard overrides:- Root: card token border radius, background, resting shadow (shadow.md), smooth transition
- Outlined variant: no shadow, card border colour
- Created Card component (
src/components/atoms/Card/Card.tsx):- Two visual variants: elevated (shadow, default) and outlined (border)
interactiveprop: hover shadow lift (shadow.lg), pointer cursor, focus-visible outlinepaddingprop: "default" (24px), "compact" (16px), "none" (raw children for full-bleed)- Uses CardContent internally for padded variants; raw children when none
- Thin wrapper pattern consistent with Button and Typography
- Created barrel export (
src/components/atoms/Card/index.ts) - Created 8 Storybook stories: Default, Variants, Interactive, PaddingPresets, PriceCardPreview, ServiceOptionPreview, WithImage, RichContent
- Preflight passed all 5 checks
- Committed and pushed to Gitea
Decisions made:
- Card uses MUI spacing units (p: 4/6) for padding presets rather than CSS variables — consistent with MUI-first approach
- Elevation set to 0 on MuiCard; box-shadow applied directly from card tokens for precise control
- Interactive hover uses CSS variable (
var(--fa-card-shadow-hover)) for shadow.lg - No new design decisions needed — Card follows existing token/design conventions from design-system.md
Open questions:
- Should interactive cards have a subtle border-colour change on hover in addition to shadow lift?
- Should we add a "selected" state for ServiceOption-style cards (e.g., brand border + brand.50 background)?
Next steps:
User to review Card in Storybook✓ Feedback received — add selected + hover bg
Session 2026-03-25g — Card selected state + hover background
Agent(s): Claude Opus (via conversation)
Work completed:
- Reviewed FA 1.0 Figma designs for card usage patterns:
- ListItemPurchaseOption (2349:39505): selectable cards with 4 states × 2 viewports
- ListItemAddItem (2350:40658): toggle/switch pattern — deferred to future Toggle component
- Added
selectedprop: brand border (2px, warm gold #BA834E) + warm background (brand.50 #FEF9F5) - Added hover background fill: interactive cards now fill with neutral.50 on hover (matching Figma's inactive→hover pattern)
- Hover on selected cards preserves warm background instead of switching to neutral
- Elevated interactive cards still get shadow lift on hover; outlined ones only get bg fill
- Added 3 new card tokens: border.selected, background.hover, background.selected
- Added 4 new stories: Selected, OptionSelect (single-select with radio semantics), MultiSelect (checkbox toggle), OnDifferentBackgrounds (white vs grey surface)
- Replaced ServiceOptionPreview story with the more complete OptionSelect and MultiSelect patterns
- Preflight passed all 5 checks
- Committed and pushed to Gitea
Decisions made:
- Selected state uses 2px brand border (not 1.5px from Figma 1.0) — 2px aligns with our focus ring width and sits on the 2px sub-grid
- Selected background uses brand.50 (warm tint) not neutral.50 (grey) — warm tint reinforces the brand connection and distinguishes selected from hovered
- Hover bg fill uses neutral.50 (not brand.50) for unselected cards — keeps hover subtle and neutral
- Toggle/switch pattern from Figma (ListItemAddItem) is a separate component concern, not Card
Next steps:
User to review Card selected/hover states in Storybook✓ ApprovedBuild Badge or Chip atom next✓ Badge done
Session 2026-03-25h — Badge atom
Agent(s): Claude Opus (via conversation)
Work completed:
- Searched FA 2.0 and Parsons 1.0 Figma files for badge/chip/tag components — none found, designed from conventions
- Created badge component tokens (
tokens/component/badge.json): height, paddingX, fontSize, iconSize, iconGap, borderRadius for sm/md — 10 tokens total - Built Badge component (
src/components/atoms/Badge/Badge.tsx):- Pill-shaped, display-only status indicator (not interactive)
- 6 colour intents: default, brand, success, warning, error, info
- 2 variants: soft (tonal bg + coloured text, default) and filled (solid bg + white text)
- 2 sizes: small (22px) and medium (26px)
- Optional leading
iconprop for contextual icons - All soft colours use CSS variables from token system — no hardcoded hex
- Warning text uses amber.700 for WCAG AA compliance
- Created 10 Storybook stories including realistic compositions (InPriceCard, ServiceStatus)
- Preflight passed all 5 checks
- Committed and pushed to Gitea
Decisions made:
- Badge defaults to soft variant — calmer, more appropriate for FA's sensitive context. Filled variant for high-priority emphasis only.
- Badge uses Box (span) not MUI Chip — keeps it simple, display-only, no interactive baggage
- Pill shape (borderRadius.full) distinguishes badges from rectangular UI elements
- Brand soft colours match Button soft (brand.200 bg, brand.700 text) for visual consistency
Next steps:
User to review Badge in Storybook✓ Approved (large size added)
Session 2026-03-25i — Impeccable integration
Agent(s): Claude Opus (via conversation)
Work completed:
- Researched pbakaus/impeccable (Apache 2.0) — 21 skills for frontend design quality
- Assessed fit for FA project — identified overlaps/conflicts, recommended selective integration
- Downloaded 14 reference files to
docs/reference/impeccable/:- 7 design guides (typography, colour, spatial, motion, interaction, responsive, ux-writing)
- 3 critique references (cognitive-load, heuristics-scoring, personas)
- 4 skill references (audit, critique, polish, frontend-design anti-patterns)
- Created
/auditskill — technical quality scoring (0-20) across 5 dimensions, adapted for FA - Created
/critiqueskill — UX review using Nielsen's 10 heuristics (0-40), with FA-specific persona checks - Updated
/review-component— added interactive states checklist (8 checks) and design anti-patterns checklist (8 checks) - Updated
/preflight— added visual QA spot-check section (advisory, non-blocking) - All changes are skill/docs only — zero code changes to existing components
Decisions made:
- Selective integration over wholesale install — only /audit, /critique, reference material, and anti-patterns merged
- Removed impeccable's dependency chain (/frontend-design → /teach-impeccable) — FA already has CLAUDE.md + docs/memory/ for design context
- Replaced impeccable's command recommendations with FA's available skills
- Critique adapted with FA-specific personas (bereaved family member, arrangement planner)
- OKLCH recommendation noted in reference but not adopted — FA uses hex-based DTCG tokens
Component status at end of session:
- Done (5): Button, Typography, Input, Card, Badge
- Planned (5 atoms): IconButton, Icon, Avatar, Divider, Chip, Link
- Planned (5 molecules): FormField, PriceCard, ServiceOption, SearchBar, StepIndicator
- Planned (5 organisms): ServiceSelector, PricingTable, ArrangementForm, Navigation, Footer
Next steps:
- Review Badge in Storybook (large size was added per user request)
Build Chip atom (interactive tags — clickable, deletable, with icon support)✓ Done- Consider running /audit or /critique on completed atoms to establish baseline scores
- Begin PriceCard molecule once Chip is done (depends on Card + Badge + Typography + Button)
Session 2026-03-25j — Chip atom
Agent(s): Claude Opus (via conversation)
Work completed:
- Created chip component tokens (
tokens/component/chip.json): height, paddingX, fontSize, iconSize, deleteIconSize, iconGap, borderRadius for sm/md — 12 tokens total - Rebuilt token pipeline — 12 new chip tokens generated across CSS/JS/JSON outputs
- Updated MUI theme (
src/theme/index.ts) with MuiChip overrides:- Pill-shaped borderRadius from token
- Two sizes: small (28px), medium (32px)
- Filled variant: neutral.200 bg for default, brand.200 bg for primary (soft/tonal, matching Badge and Button soft)
- Outlined variant: neutral.300 border for default, brand.400 border for primary
- Hover states per variant × colour
- Delete icon hover colour change
- Focus-visible outline (brand.500, 2px offset)
- Created Chip component (
src/components/atoms/Chip/Chip.tsx):- Wraps MUI Chip with React.forwardRef
- Custom
selectedprop: promotes colour to primary, outlined selected gets brand border + warm bg - Two variants: filled (tonal, default), outlined (border)
- Two colours: default (neutral), primary (brand)
- Interactive modes: clickable (via onClick), deletable (via onDelete), both, or static
- All MUI ChipProps passed through
- Created barrel export (
src/components/atoms/Chip/index.ts) - Created 10 Storybook stories: Default, Variants, Sizes, WithIcons, Clickable, Deletable, Selected, FilterChips (interactive toggle demo), RemovableTags (interactive dismiss demo), InServiceOption (realistic card composition), CompleteMatrix
- Preflight passed all 5 checks
Decisions made:
- Chip uses MUI Chip wrapper (unlike Badge which uses raw Box) — MUI Chip provides built-in keyboard navigation, delete icon, and click handling that would be complex to reimplement
- Chip defaults to
filledvariant with soft/tonal colours (matching Badge soft and Button soft patterns) — NOT MUI's default opaque fill - Only
defaultandprimarycolours initially — secondary/error/etc. added when needed (YAGNI) - Selected state auto-promotes to primary colour unless colour is explicitly set — mirrors Card's selected brand treatment
- No new design decision IDs needed — Chip follows established conventions
Component status at end of session:
- Done (5): Button, Typography, Input, Card, Badge
- Review (1): Chip
- Planned (4 atoms): IconButton, Icon, Avatar, Divider, Link
- Planned (5 molecules): FormField, PriceCard, ServiceOption, SearchBar, StepIndicator
- Planned (5 organisms): ServiceSelector, PricingTable, ArrangementForm, Navigation, Footer
Next steps:
User to review Chip in Storybook✓ ApprovedConsider running /audit or /critique on completed atoms to establish baseline scores✓ Done- Begin PriceCard molecule (depends on Card + Badge + Typography + Button + Chip)
Session 2026-03-25k — Audit, P1 fixes, Switch + Radio atoms
Agent(s): Claude Opus (via conversation)
Work completed:
- Ran /audit on all 5 completed atoms (Button, Typography, Input, Card, Badge)
- Average score: 18/20 (Excellent)
- 2 P1 issues identified and fixed, 7 P2s documented, 5 P3s noted
- Fixed P1: Button loading state now announces to screen readers (aria-busy + visually-hidden text)
- Fixed P1: Card interactive now has tabIndex={0} and role="button" for keyboard operability
- Fixed P2: Card Record<string, any> → Theme type for type safety
- Reviewed Parsons 1.0 Figma "Toggles" board (node 2322:42538) — identified 4 new atoms: Switch, Radio, ColourToggle, Slider
- Added all 4 to component registry (ColourToggle and Slider deferred)
- Created switch component tokens (
tokens/component/switch.json): track width/height/borderRadius, thumb size — 4 tokens - Created radio component tokens (
tokens/component/radio.json): size, dotSize — 2 tokens - Updated MUI theme with MuiSwitch overrides: bordered pill track, brand.500 active fill, focus-visible ring
- Updated MUI theme with MuiRadio overrides: neutral.400 unchecked, brand.500 checked, hover states
- Created Switch component — thin MUI wrapper with forwardRef
- Created Radio component — thin MUI wrapper with forwardRef
- Created Switch stories (4): Default, States, ServiceAddOns (interactive add-on toggle demo), WithLabels
- Created Radio stories (5): Default, States, RadioGroup, CardSelection (interactive card + radio demo), PaymentMethod
- Preflight passed all 5 checks
Decisions made:
- Switch implements Figma "Style One" (bordered pill) only — other styles deferred as variants if needed
- Switch/Radio are ultra-thin wrappers — all styling via MUI theme overrides, no component-level sx
- ColourToggle and Slider deferred until their consuming organisms are built
Component status at end of session:
- Done (5): Button, Typography, Input, Card, Badge
- Review (3): Chip, Switch, Radio
- Planned (6 atoms): IconButton, Icon, Avatar, Divider, ColourToggle, Slider, Link
- Planned (5 molecules): FormField, PriceCard, ServiceOption, SearchBar, StepIndicator
- Planned (5 organisms): ServiceSelector, PricingTable, ArrangementForm, Navigation, Footer
Next steps:
User to review Switch and Radio in Storybook✓ ApprovedBegin PriceCard molecule✓ Replaced with ProviderCard (see below)- Address P2 audit issues in a future cleanup pass
Session 2026-03-25l — ProviderCard molecule (first molecule)
Agent(s): Claude Opus (via conversation)
Work completed:
- Reviewed 3 Figma designs: Provider Cards (5503:44422), Service Venue (2997:83018), Map Pin Card (5369:140263)
- Captured business context: verified vs unverified providers, Parsons partner strategy, map + list layout
- Replaced generic "PriceCard" in registry with 3 specific molecules: ProviderCard, VenueCard, MapCard
- Saved business context to auto-memory (project_listing_cards.md)
- Created plan via /plan mode — component API, card structure, token plan, story plan
- Created providerCard component tokens (
tokens/component/providerCard.json): image.height, logo.size, footer.background/paddingX/paddingY, content.padding/gap — 7 tokens - Built ProviderCard molecule (
src/components/molecules/ProviderCard/ProviderCard.tsx):- Composes Card (interactive, padding="none") + Badge + Typography
- Verified variant: hero image (CSS bg-image cover), logo overlay (48px circle, absolute positioned, overlaps content), "Trusted Partner" badge (filled brand), capability badge
- Unverified variant: text-only, same content area + footer
- Footer bar: warm brand.100 bg, "Packages from $X" + ChevronRight
- Accessibility: aria-label on reviews, aria-hidden on decorative icons, alt text on logo
- All values from token CSS variables, no hardcoded hex
- Created 9 Storybook stories: Default, VerifiedProvider, UnverifiedProvider, ListLayout (mixed), CapabilityVariants, EdgeCases, Responsive, OnDifferentBackgrounds, InteractiveDemo
- Preflight passed all 5 checks
- Logged D026-D030 in decisions log
Decisions made:
- D026: Molecules compose atoms via sx — no MUI theme overrides
- D027: Image as URL string (CSS bg-image), logo as URL string (
)
- D028: Logo 48px (not 75px Figma) for card width proportion
- D029: Footer built in via startingPrice prop, not a slot
- D030: verified is explicit boolean, not derived from imageUrl
Component status at end of session:
- Done (7): Button, Typography, Input, Card, Badge, Chip, Switch, Radio
- Review (1 molecule): ProviderCard
- Planned (7 atoms): IconButton, Icon, Avatar, Divider, ColourToggle, Slider, Link
- Planned (5 molecules): VenueCard, MapCard, ServiceOption, SearchBar, StepIndicator, FormField
- Planned (5 organisms): ServiceSelector, PricingTable, ArrangementForm, Navigation, Footer
Next steps:
User to review ProviderCard in Storybook✓ Feedback received, iterated in session 25m
Session 2026-03-25m — ProviderCard v2 refinements from user feedback
Agent(s): Claude Opus (via conversation)
Work completed:
- Iterated on ProviderCard based on 5 feedback items from user review
- Logo: circle → 64px rounded rectangle (8px radius,
borderRadius.md). Positioned fully inside image area (absolute, bottom-left) with white border + shadow. Eliminates dead space — name sits directly below image. - Footer removed: "View packages >" bar was redundant (whole card is clickable, price already in content). Removed 3 footer tokens (
footer.background,.paddingX,.paddingY). - Price typography: Split into "Packages from" (body2, 14px, secondary) + price (h6, 16px, weight 500, primary). Lighter, streamlined ecommerce feel vs old blocky labelLg/700.
- Verified badge: Bumped from
size="small"tosize="medium"for visibility. - Capability badge: Bumped to
size="medium". Added trailingInfoOutlinedIconand newcapabilityDescriptionprop — wraps badge in MUI Tooltip on hover/focus for plain-language definitions of industry jargon. - Unverified card differentiation: 3px
borderTop(neutral.200) as visual anchor. ListLayout story now on neutral.50 background. - Caption weight fix (system-wide): Caption and CaptionSm bumped from fontWeight 400 (Regular) → 500 (Medium) in semantic typography tokens. Aligns with D019 — user found Regular too light for Montserrat.
- Meta row: Location/reviews dropped from body2 (14px) → caption (12px) with 14px icons for clearer tertiary hierarchy.
- Updated all stories with
capabilityDescriptiontooltips for 3 capability types - Preflight passed all 5 checks
Decisions made:
- Logo positioned fully inside image (no overlap into content) — tried flex-row overlap approach first but it "dug into" the photo and pushed the name sideways
- Footer removal: card's interactive hover + price in content are sufficient affordance
- Caption weight 500: extends D019 (body weight = Medium) to all Montserrat text variants. Only display (Noto Serif SC) stays at 400 per D018.
- Info icon for capability badges: trailing position (after label),
cursor: helpwhen tooltip active
Token changes:
providerCard.logo.size: 56px → 64pxproviderCard.logo.borderRadius: new, →{borderRadius.md}(8px)providerCard.footer.*: 3 tokens removed (footer eliminated)typography.caption.fontWeight:{fontWeight.regular}→{fontWeight.medium}typography.captionSm.fontWeight:{fontWeight.regular}→{fontWeight.medium}
Component status at end of session:
- Done (8): Button, Typography, Input, Card, Badge, Chip, Switch, Radio
- Review (1 molecule): ProviderCard (v2, user approved direction)
- Planned (6 atoms): IconButton, Icon, Avatar, Divider, ColourToggle, Slider, Link
- Planned (5 molecules): VenueCard, MapCard, ServiceOption, SearchBar, StepIndicator, FormField
- Planned (5 organisms): ServiceSelector, PricingTable, ArrangementForm, Navigation, Footer
Next steps:
Build VenueCard molecule✓ DoneAddress P2 audit issues✓ DoneAudit ProviderCard v2✓ Done (17/20, P2s fixed)
Session 2026-03-25n — VenueCard molecule, P2 fixes, ProviderCard audit
Agent(s): Claude Opus (via conversation)
Work completed:
- Reviewed Figma venue card design (node 2997:83018) — photo + name + location + capacity + price
- Created venueCard component tokens (
tokens/component/venueCard.json): image.height (180px), content.padding (spacing.3), content.gap (spacing.1) — 3 tokens - Built VenueCard molecule (
src/components/molecules/VenueCard/VenueCard.tsx):- Composes Card (interactive, padding="none") + Typography
- Hero image with
role="img"+ aria-label for screen readers - Meta row: location (pin icon) + capacity with "guests" suffix for clarity
- Price with "From" qualifier (split typography like ProviderCard)
- No verification tiers, no logo, no badges — simpler than ProviderCard
- Created 6 Storybook stories: Default, ListLayout, EdgeCases, Responsive, OnDifferentBackgrounds, InteractiveDemo
- Ran /critique on VenueCard: 33/40 (Good). Applied P2 fixes before commit:
- Capacity: bare number → "X guests" for visible context
- Price: bare "$900" → "From $900" for transparency
- Image: added
role="img"+aria-labelfor screen readers
- Fixed 6 P2 audit issues across atom components:
- Input:
Record<string, any>→Themetype on boxShadow accessor - Button: documented aria-label requirement for icon-only usage
- Badge: documented aria-label for icon-only badges
- Switch: strengthened a11y docs with FormControlLabel example
- Radio: strengthened a11y docs with RadioGroup + FormControlLabel example
- Chip: documented aria-label for icon-only deletable chips
- Input:
- Ran /audit on ProviderCard v2: 17/20 (Good). Fixed 3 P2s:
- Hero image: added
role="img"+aria-labelfor screen readers - Logo shadow: hardcoded rgba →
var(--fa-shadow-sm) - Logo border: hardcoded white →
var(--fa-color-white)
- Hero image: added
Decisions made:
- VenueCard follows same token structure as ProviderCard (image.height, content.padding, content.gap) for visual consistency in list views
- Capacity shows "X guests" suffix — bare number was confusing in critique
- Price shows "From $X" — matches ProviderCard's "Packages from" pattern for transparency
Component status at end of session:
- Done (8): Button, Typography, Input, Card, Badge, Chip, Switch, Radio
- Review (2 molecules): ProviderCard (v2, audit 17/20), VenueCard (critique 33/40)
- Planned (6 atoms): IconButton, Icon, Avatar, Divider, ColourToggle, Slider, Link
- Planned (4 molecules): MapCard, ServiceOption, SearchBar, StepIndicator, FormField
- Planned (5 organisms): ServiceSelector, PricingTable, ArrangementForm, Navigation, Footer
Next steps:
User to review VenueCard in Storybook✓ ApprovedBuild next atoms (IconButton, Divider, Link)✓ Done
Session 2026-03-25n (continued) — IconButton, Divider, Link atoms
Agent(s): Claude Opus (via conversation)
Work completed:
- Built IconButton atom — wraps MUI IconButton with FA theme overrides:
- 3 sizes reusing Button height tokens (sm 32px, md 40px, lg 48px)
- Rounded rect shape (borderRadius.md), brand hover colours, focus ring
- 4 colour options: default, primary, secondary, error
- 5 stories including CommonUseCases (card toolbar, dialog close, nav toggle)
- Built Divider atom — wraps MUI Divider with FA border token:
- Horizontal/vertical orientation, fullWidth/inset/middle variants
- Text children support (MUI built-in)
- 6 stories including InContent and NavigationList patterns
- Built Link atom — wraps MUI Link with FA brand tokens:
- Copper colour (brand.600, 4.8:1 contrast) by default
- Underline on hover, focus-visible ring, fontWeight 500
- 7 stories including Inline (body text), Navigation, FooterLinks
- Added MuiIconButton, MuiDivider, MuiLink overrides to theme
Decisions made:
- IconButton uses rounded rect (borderRadius.md) not circle — consistent with Button. Circle can be achieved with sx if needed.
- Link defaults to underline="hover" — always-underlined links feel heavy in FA's clean aesthetic, but the underline is important for discoverability so it appears on hover.
- No new component tokens — IconButton reuses Button tokens, Divider uses palette.divider, Link uses palette colours.
Component status at end of session:
- Done (8): Button, Typography, Input, Card, Badge, Chip, Switch, Radio
- Review (3 atoms): IconButton, Divider, Link
- Review (2 molecules): ProviderCard (v2, audit 17/20), VenueCard (critique 33/40)
- Planned (3 atoms): Icon, Avatar, ColourToggle, Slider
- Planned (4 molecules): MapCard, ServiceOption, SearchBar, StepIndicator, FormField
- Planned (5 organisms): ServiceSelector, PricingTable, ArrangementForm, Navigation, Footer
Next steps:
User to review IconButton, Divider, Link in Storybook✓ ApprovedBuild ServiceOption molecule✓ Done
Session 2026-03-25n (continued) — ServiceOption molecule
Agent(s): Claude Opus (via conversation)
Work completed:
- Reviewed 2 Figma components: ListItemPurchaseOption (2349:39505) and ListItemAddItem (2350:40658)
- ListItemPurchaseOption: click-to-select card with 4 states (inactive, hover, active, active hover)
- ListItemAddItem: toggle with Switch — deferred as a future AddOnOption molecule
- Built ServiceOption molecule (
src/components/molecules/ServiceOption/ServiceOption.tsx):- Composes Card (interactive, selected) + Typography
- Heading row: name (h6) + optional price (h6, brand colour, right-aligned, nowrap)
- Optional description below (body2, text.secondary)
- Selected state via Card's built-in brand border + warm bg
- Disabled state with opacity token (--fa-opacity-disabled) + pointer-events: none
- role="radio" + aria-checked for proper single-select group semantics
- Uses card.padding.compact (16px) for content padding
- Created 7 stories: Default, Selected, ServiceTypeSelection (interactive radiogroup), CoffinSelection (interactive 4-option), WithoutPrice, Disabled, EdgeCases
- No new tokens — ServiceOption reuses Card tokens (padding.compact, border.selected, etc.)
Decisions made:
- ServiceOption uses role="radio" + aria-checked — correct for single-select groups within a radiogroup. Parent wraps in role="radiogroup".
- Price right-aligned in heading row — natural scanning pattern (name on left, cost on right, like a menu)
- No component-specific tokens needed — Card's existing tokens handle all visual states
- AddOnOption (ListItemAddItem with Switch) deferred — will compose Card + Switch when arrangement form organisms are built
Component status at end of session:
- Done (8): Button, Typography, Input, Card, Badge, Chip, Switch, Radio
- Review (3 atoms): IconButton, Divider, Link
- Review (3 molecules): ProviderCard, VenueCard, ServiceOption
- Planned (3 atoms): Icon, Avatar, ColourToggle, Slider
- Planned (3 molecules): MapCard, SearchBar, StepIndicator, FormField
- Planned (5 organisms): ServiceSelector, PricingTable, ArrangementForm, Navigation, Footer
Next steps:
Build SearchBar molecule✓ DoneBuild AddOnOption molecule✓ DoneBuild StepIndicator molecule✓ DoneBuild Navigation organism✓ Done
Session 2026-03-25o — SearchBar, AddOnOption, StepIndicator molecules + Navigation organism
Agent(s): Claude Opus (via conversation)
Work completed:
- Built SearchBar molecule (
src/components/molecules/SearchBar/):- Composes Input (with search icon) + optional Button for provider/venue search
- Enter-to-submit, progressive clear button (appears when text present), inline loading spinner
- Guards empty submissions (
value.trim()), refocuses input after clear role="search"landmark, two sizes aligned with Input/Button- Critique: 35/40 (Good). P2 fixes applied before commit.
- 8 stories: Default, WithButton, SmallSize, WithPreloadedValue, Loading, Disabled, ProviderSearch, VenueSearch
- Built AddOnOption molecule (
src/components/molecules/AddOnOption/):- Composes Card (interactive, selected) + Typography + Switch
- Maps to Figma ListItemAddItem (2350:40658) — toggle for optional extras
- Heading + optional price + description + Switch right-aligned
- Click anywhere on card toggles the switch (stopPropagation on switch itself)
aria-labelledbyconnects switch to heading text- 7 stories: Default, Checked, ServiceAddOns (interactive list with running total), WithoutPrice, WithoutDescription, Disabled, EdgeCases
- Built StepIndicator molecule (
src/components/molecules/StepIndicator/):- Maps to Figma Progress Bar - Steps (2375:47468) — horizontal segmented bar
- Brand gold for completed/current steps, grey (divider) for upcoming
- Responsive bar height (10px desktop, 6px mobile), responsive labels
- Current step label bolded,
role="navigation"+aria-current="step" - 7 stories: Default, AllStates, TwoSteps, ManySteps, Interactive (nav demo), Completed, NarrowContainer
- Built Navigation organism (
src/components/organisms/Navigation/):- First organism in the design system
- Maps to Figma Main Nav (14:108) + Mobile Header (2391:41508)
- Desktop: sticky AppBar, logo left, nav Link items right, optional CTA Button
- Mobile: hamburger IconButton + Drawer with nav list, CTA, Divider, help footer with phone
- Warm surface background (brand.50), border bottom
- Composes AppBar, Link, IconButton, Button, Divider, Drawer, Typography
- 6 stories: Default, WithCTA, WithPageContent (sticky scroll demo), Minimal, ExtendedNavigation, MobilePriceTracker
- All 4 components: TypeScript compiles, Storybook builds, committed and pushed
Decisions made:
- SearchBar guards empty submissions and disables button when empty — prevents wasted requests
- AddOnOption uses click-anywhere-to-toggle pattern (stopPropagation on Switch to avoid double-toggle)
- StepIndicator uses
palette.dividerfor incomplete steps — grey/sage from theme, not hardcoded - Navigation uses
var(--fa-color-surface-warm)background — matches Figma's warm grey #F4F3EF - Navigation nav link colour uses brand.900 (#51301B) — matches Figma "Brown Two" token
- No new component tokens needed for any of the 4 components — all reuse existing tokens
Component status at end of session:
- Done (8): Button, Typography, Input, Card, Badge, Chip, Switch, Radio
- Review (3 atoms): IconButton, Divider, Link
- Review (6 molecules): ProviderCard, VenueCard, ServiceOption, SearchBar, AddOnOption, StepIndicator
- Review (1 organism): Navigation
- Planned (3 atoms): Icon, Avatar, ColourToggle, Slider
- Planned (2 molecules): MapCard, FormField
- Planned (4 organisms): ServiceSelector, PricingTable, ArrangementForm, Footer
Post-review fixes (same session):
- SearchBar: button height aligned via explicit CSS var height, icon-to-text gap tightened (adornment mr: 0.5), focus ring gap increased (gap 6px → 10px)
- AddOnOption: price moved to own row below heading, heading row centre-aligned so short headings (no description) align with switch, heading-to-price margin removed
- AddOnOption + ServiceOption: added optional
maxDescriptionLinesprop with CSS line-clamp + "View more"/"View less" toggle (caption size, text.secondary, weight 400). Omit prop for no limit.
Next steps:
Build Footer organism(next)Build ServiceSelector organism(next)Consider FormField molecule(next)Remaining P3s(next)
Session 2026-03-25p — Review completion + Navigation fixes
Agent(s): Claude Opus (via conversation)
Work completed:
- Completed review of all components — user approved all atoms + molecules with no changes
- Applied 4 Navigation fixes from user feedback:
- Added "Provider Portal" to default nav items
- Integrated real FA logo SVGs from
brandassets/brandlogo/(full wordmark desktop, short icon mobile) - Changed nav background from warm (
surface.warm/ brand.50) to grey (surface.subtle/ neutral.50) - Removed
mobileTrailingprop andMobilePriceTrackerstory — speculative feature not in design
- Added
staticDirs: ['../brandassets']to Storybook config for logo serving - Updated component-registry.md: promoted 11 atoms + 6 molecules + 1 organism from "review" to "done"
- TypeScript compiles, Storybook builds
Decisions made:
- Nav background is grey (neutral.50) not warm (brand.50) — per user's Figma reference
- "Log in" label kept as-is — universally understood, user confirmed
- mobileTrailing prop removed entirely — was over-reading Figma's mobile header
Component status at end of session:
- Done (11 atoms): Button, Typography, Input, Card, Badge, Chip, Switch, Radio, IconButton, Divider, Link
- Done (6 molecules): ProviderCard, VenueCard, ServiceOption, SearchBar, AddOnOption, StepIndicator
- Done (1 organism): Navigation
- Planned (3 atoms): Icon, Avatar, ColourToggle, Slider
- Planned (2 molecules): MapCard, FormField
- Planned (4 organisms): ServiceSelector, PricingTable, ArrangementForm, Footer
Next steps:
Build Footer organism✓ DoneBuild ServiceSelector organism✓ Done- Consider FormField molecule if Input's built-in label/helperText proves insufficient
- Remaining P3s: InfoOutlinedIcon sizing in ProviderCard, image loading placeholder, accent bar 3px→4px
Session 2026-03-25p (continued) — Footer + ServiceSelector organisms
Agent(s): Claude Opus (via conversation)
Work completed:
- Built Footer organism (
src/components/organisms/Footer/):- Dark espresso (brand.950) surface with inverse white text
- Logo + tagline + contact info (phone/email with tel:/mailto: links) in left column
- Configurable link group columns with heading +
<ul>list - Bottom legal bar: copyright + legal links (Privacy, Terms, Accessibility)
- Semantic HTML:
<footer>,<nav aria-label>per link group,<ul>for link lists - Responsive: stacks to single column on mobile, side-by-side on desktop
- 5 stories: Default, Minimal, WithContactOnly, TwoColumns, FullPage (Nav + content + Footer)
- Critique: 38/40 (Excellent). P2 fixes applied: legal links bumped from 11px → 12px, nav landmarks added
- Built ServiceSelector organism (
src/components/organisms/ServiceSelector/):- Single-select panel composing Typography + ServiceOption × n + Button
- Heading + optional subheading + radiogroup of ServiceOption cards + optional continue button
- Continue button auto-disables when nothing selected (overridable via
continueDisabled) maxDescriptionLinespass-through to ServiceOption for truncation- 7 stories: Default, PreSelected, Interactive, CoffinSelection, WithTruncatedDescriptions, WithoutContinue, WithDisabledOptions, InArrangementFlow (with StepIndicator)
- No new tokens needed — both organisms reuse existing token system
- TypeScript compiles, Storybook builds
Decisions made:
- Footer uses brand.950 (espresso) background — darkest brand tone for maximum contrast with white text, warm but professional
- Footer link groups get individual
<nav aria-label>landmarks — better screen reader navigation - ServiceSelector is a controlled component: parent manages
selectedId+onSelect. Keeps state lifting simple for arrangement flow. - Continue button defaults to disabled when nothing selected — prevents empty submissions without explicit error messages
Component status at end of session:
- Done (11 atoms): Button, Typography, Input, Card, Badge, Chip, Switch, Radio, IconButton, Divider, Link
- Done (6 molecules): ProviderCard, VenueCard, ServiceOption, SearchBar, AddOnOption, StepIndicator
- Done (1 organism): Navigation
- Review (2 organisms): Footer (critique 38/40), ServiceSelector
- Planned (3 atoms): Icon, Avatar, ColourToggle, Slider
- Planned (2 molecules): MapCard, FormField
- Planned (2 organisms): PricingTable, ArrangementForm
Next steps:
User to review Footer + ServiceSelector✓ ApprovedBuild ArrangementFormRemoved — premature, need more building blocksBuild Package Select page components✓ Done
Session 2026-03-26a — Reviews, Navigation fixes, Package Select page components
Agent(s): Claude Opus (via conversation)
Work completed:
- Completed review of all 10 "review" components — all approved to done
- Navigation fixes from user feedback:
- Added "Provider Portal" to nav items
- Integrated real FA logo SVGs from
brandassets/brandlogo/ - Changed nav background from warm (brand.50) → grey (neutral.50 / surface.subtle)
- Removed
mobileTrailingprop and MobilePriceTracker story (speculative) - Added
staticDirsto Storybook for brand asset serving
- Built Footer organism (critique 38/40):
- Dark espresso bg, logo + tagline + contact + link columns + legal bar
- P2 fixes: extracted overline sx, used overlineSm variant, bumped legal links to 12px
- Built ServiceSelector organism:
- Single-select panel with radiogroup, continue button auto-disables
- WithLineLimit story for description truncation
- Built and removed ArrangementForm organism (premature — user flagged)
- Analysed Package Select page from Figma (5405:181955):
- Identified gaps: LineItem, ProviderCardCompact, PackageDetail
- Recommended Chip filter bar for funeral type switching
- Built LineItem molecule (audit 19/20):
- Name + info tooltip + optional price, allowance asterisk, total variant
- Font weight 500 (D019), prices text.secondary for readability hierarchy
- aria-label on info icon for screen readers
- Built ProviderCardCompact molecule:
- Horizontal layout: image left, name + location + rating right
- Built PackageDetail organism (audit 19/20):
- Warm header band with "Package" overline, name, price in brand colour
- sections (before total) + total + extras (after total with subtext)
- compareLoading prop for Compare button spinner
- T&C grey footer, responsive button stacking
- Section headings h6 (16px/600) vs LineItem body2 (14px/500) for hierarchy
- Full PackageSelectPage story with filter chips, ServiceOption list, sticky detail
- Multiple audit + review iterations with user feedback applied
Decisions made:
- Navigation background is grey (surface.subtle), not warm — per user
- "Make Arrangement" is the FA term for selecting/committing to a package
- PackageDetail structure: sections → total → extras. Total separates included content from additional-cost items. Business-critical distinction.
- LineItem prices use text.secondary — name reads first, price supports. Total row stays prominent.
- Chip filter bar for funeral type switching — visible, discoverable, matches existing Chip component
- Always audit before presenting to user — saved as feedback memory
Component status at end of session:
- Done (11 atoms): Button, Typography, Input, Card, Badge, Chip, Switch, Radio, IconButton, Divider, Link
- Done (10 molecules): ProviderCard, VenueCard, ServiceOption, SearchBar, AddOnOption, StepIndicator, LineItem, ProviderCardCompact
- Done (4 organisms): Navigation, Footer, ServiceSelector, PackageDetail
- Planned (3 atoms): Icon, Avatar, ColourToggle, Slider
- Planned (2 molecules): MapCard, FormField
- Planned (2 organisms): PricingTable, ArrangementForm
Next steps:
Review next key page (Package Select)✓ DoneBuild homepage FuneralFinder organism✓ Done (v2 — conversational redesign)
Session 2026-03-26b — FuneralFinder organism + further PackageDetail refinements
Agent(s): Claude Opus (via conversation)
Work completed:
- PackageDetail review refinements from user feedback:
- Section headings bumped from label (14px) to h6 (16px/600) — now stand out against line items
- Added Divider + subtext before Extras ("These items can be added at additional cost")
- T&C line height reduced 1.5 → 1.3
- Item spacing increased 12px → 16px
- Warm header band (surface.warm) with "Package" overline, name, price in brand colour
- Compare button loading state (compareLoading prop)
- Complimentary items now correctly shown before total
- Total row padding balanced (top matched to bottom)
- Audit: 19/20 (Excellent)
- Built FuneralFinder organism — homepage hero search widget:
- v1: Literal translation of marketing reference — numbered steps, uppercase overlines, cramped options. User feedback: "looks like a government form, not gentle guidance"
- v2 (current): Complete conversational redesign:
- Warm questions: "How can we help you today?" not "I'M HERE TO"
- ChoiceCards: generous padding, descriptions, check icon on selection
- TypePills: pill-shaped buttons for dynamic funeral type list
- CompletedRow: "I'm here to Arrange a funeral now · Change"
- One question at a time — true progressive disclosure
- CTA only appears at location step — no disabled button staring at you
- No step numbers or badges
- Flow: Intent → Planning For (conditional) → Funeral Type → Location → CTA
- Audit: 17/20 (Good). P1/P2 fixes applied: aria-labels, radiogroup semantics, edit affordance
- 5 stories: Default, FewerTypes, CustomHeading, InHeroDesktop, InHeroMobile
Decisions made:
- "Make Arrangement" is FA's term for selecting/committing to a package
- PackageDetail structure: sections → total → extras (business-critical distinction)
- LineItem prices use text.secondary for readability hierarchy
- FuneralFinder uses conversational approach, not procedural/form-like
- Funeral types are prop-driven (dynamic from API)
- Pre-plan "for someone else" affects the arrangement journey
- Location needs a reusable Autocomplete atom (future work)
- "Find funeral directors" is the CTA text (not "Find providers")
Component status at end of session:
- Done (11 atoms): Button, Typography, Input, Card, Badge, Chip, Switch, Radio, IconButton, Divider, Link
- Done (10 molecules): ProviderCard, VenueCard, ServiceOption, SearchBar, AddOnOption, StepIndicator, LineItem, ProviderCardCompact
- Done (4 organisms): Navigation, Footer, ServiceSelector, PackageDetail
- Review (1 organism): FuneralFinder (v2 conversational — user wants further changes)
- Planned (3 atoms): Icon, Avatar, ColourToggle, Slider
- Planned (2 molecules): MapCard, FormField, Autocomplete
- Planned (2 organisms): PricingTable, ArrangementForm
Next steps:
- User to continue refining FuneralFinder — further UX changes planned
- Homepage redesign — FuneralFinder is one organism on the page, full homepage composition next
- Build Autocomplete atom for location search (reusable pattern for other areas)
- P3 cleanup: inverse logo SVG, InfoOutlinedIcon sizing in ProviderCard, image placeholder, accent bar 3px→4px