Files
Parsons/docs/memory/session-log.md
Richie f31e37c837 Add ProviderCard molecule — first molecule in design system
First molecule component. Listing card for funeral providers on the
provider select screen (map + scrollable list layout).

- Verified providers: hero image, 48px logo overlay, "Trusted Partner"
  badge, name, location, reviews, capability badge, footer with price
- Unverified providers: text-only with same content alignment
- 7 component tokens (image height, logo size, footer/content spacing)
- Composes Card (interactive, padding="none") + Badge + Typography
- Capability badges accept arbitrary label + colour (categories may change)
- Footer bar with warm brand.100 bg, "Packages from $X >"
- 9 Storybook stories including mixed list layout demo
- Decisions D026-D030 logged

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 17:39:03 +11:00

33 KiB
Raw Blame History

Session log

This file tracks work completed across Claude Code sessions. Every agent MUST read this file before starting work and update it after completing work.

Format

Each entry follows this structure:

### Session [date] — [brief description]
**Agent(s):** [which agents were active]
**Work completed:**
- [bullet points of what was done]
**Decisions made:**
- [any design/architecture decisions with brief rationale]
**Open questions:**
- [anything unresolved that needs human input]
**Next steps:**
- [what should happen next]

Sessions

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.json with 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.md format with YAML frontmatter
  • Fixed critical Style Dictionary v4 config: converted from CommonJS to ESM (StyleDictionary class API)
  • Changed build:tokens script from style-dictionary build --config ... to node style-dictionary/config.js
  • Added "type": "module" to package.json for ESM support
  • Changed SD output from tokens.ts to tokens.js (Style Dictionary v4 generates JS, not TS)
  • Registered @storybook/addon-designs in .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.sh to check for .storybook/ dir instead of node_modules/@storybook
  • Verified npm run build:tokens runs successfully (empty output expected — no tokens yet)
  • Verified Storybook runs at http://localhost:6006

Decisions made:

  • Skills use .claude/skills/<name>/SKILL.md format (not .claude/commands/)
  • Style Dictionary v4 config is a standalone ESM script run via node, not CLI
  • British spelling for filenames (colours.json), standard color namespace for token paths

Open questions:

  • Slash commands /create-tokens etc. 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 working
  • Begin Step 1: /create-tokens with brand colours, fonts, and reference material ✓ Done

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: true flag (required for DTCG format CSS generation)
  • Generated outputs:
    • CSS: 245 custom properties in src/theme/generated/tokens.css with var() references for semantic tokens
    • JS: 258 named exports in src/theme/generated/tokens.js
    • JSON: flat export in tokens/export/tokens-flat.json
  • 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: true default prop
    • Custom xs size 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 optional underline prop, 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-material over 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 soft variant 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 baseline
  • Build Typography atom ✓ Done
  • Add 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.html and index.html
  • Created Typography component (src/components/atoms/Typography/Typography.tsx):
    • Thin wrapper around MUI Typography with React.forwardRef
    • Custom prop: maxLines for 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-describedby connection 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)
    • interactive prop: hover shadow lift (shadow.lg), pointer cursor, focus-visible outline
    • padding prop: "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 selected prop: 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 ✓ Approved
  • Build 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 icon prop 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 /audit skill — technical quality scoring (0-20) across 5 dimensions, adapted for FA
  • Created /critique skill — 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 selected prop: 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 filled variant with soft/tonal colours (matching Badge soft and Button soft patterns) — NOT MUI's default opaque fill
  • Only default and primary colours 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 ✓ Approved
  • Consider 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 ✓ Approved
  • Begin 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 — especially ListLayout story for verified/unverified alignment
  • Build VenueCard molecule (simpler — always has photo, location, capacity, price)
  • Consider MapCard as a deferred item until map integration
  • Address P2 audit issues in a future cleanup pass