From f121ac71686e412026cf6fb4a2b7a1a8f8420eba Mon Sep 17 00:00:00 2001 From: Richie Date: Thu, 16 Apr 2026 16:02:06 +1000 Subject: [PATCH] Strip AI tooling and working docs for dev push --- .claude/agents/component-builder.md | 82 -- .claude/agents/story-writer.md | 70 -- .claude/agents/token-architect.md | 57 -- .claude/skills/adapt/SKILL.md | 130 --- .claude/skills/audit/SKILL.md | 120 --- .claude/skills/build-atom/SKILL.md | 28 - .claude/skills/build-molecule/SKILL.md | 30 - .claude/skills/build-organism/SKILL.md | 34 - .claude/skills/clarify/SKILL.md | 150 --- .claude/skills/create-tokens/SKILL.md | 20 - .claude/skills/critique/SKILL.md | 124 --- .claude/skills/harden/SKILL.md | 135 --- .claude/skills/normalize/SKILL.md | 146 --- .claude/skills/polish/SKILL.md | 146 --- .claude/skills/preflight/SKILL.md | 111 --- .claude/skills/publish/SKILL.md | 93 -- .claude/skills/quieter/SKILL.md | 131 --- .claude/skills/review-component/SKILL.md | 68 -- .claude/skills/status/SKILL.md | 35 - .claude/skills/sync-tokens/SKILL.md | 22 - .claude/skills/typeset/SKILL.md | 116 --- .claude/skills/write-stories/SKILL.md | 29 - .claude/skills/write-tests/SKILL.md | 101 -- docs/memory/component-registry.md | 122 --- docs/memory/session-log.md | 1136 ---------------------- docs/reference/component-lifecycle.md | 154 --- docs/reference/funeral-finder-logic.md | 203 ---- 27 files changed, 3593 deletions(-) delete mode 100644 .claude/agents/component-builder.md delete mode 100644 .claude/agents/story-writer.md delete mode 100644 .claude/agents/token-architect.md delete mode 100644 .claude/skills/adapt/SKILL.md delete mode 100644 .claude/skills/audit/SKILL.md delete mode 100644 .claude/skills/build-atom/SKILL.md delete mode 100644 .claude/skills/build-molecule/SKILL.md delete mode 100644 .claude/skills/build-organism/SKILL.md delete mode 100644 .claude/skills/clarify/SKILL.md delete mode 100644 .claude/skills/create-tokens/SKILL.md delete mode 100644 .claude/skills/critique/SKILL.md delete mode 100644 .claude/skills/harden/SKILL.md delete mode 100644 .claude/skills/normalize/SKILL.md delete mode 100644 .claude/skills/polish/SKILL.md delete mode 100644 .claude/skills/preflight/SKILL.md delete mode 100644 .claude/skills/publish/SKILL.md delete mode 100644 .claude/skills/quieter/SKILL.md delete mode 100644 .claude/skills/review-component/SKILL.md delete mode 100644 .claude/skills/status/SKILL.md delete mode 100644 .claude/skills/sync-tokens/SKILL.md delete mode 100644 .claude/skills/typeset/SKILL.md delete mode 100644 .claude/skills/write-stories/SKILL.md delete mode 100644 .claude/skills/write-tests/SKILL.md delete mode 100644 docs/memory/component-registry.md delete mode 100644 docs/memory/session-log.md delete mode 100644 docs/reference/component-lifecycle.md delete mode 100644 docs/reference/funeral-finder-logic.md diff --git a/.claude/agents/component-builder.md b/.claude/agents/component-builder.md deleted file mode 100644 index 2da0ce3..0000000 --- a/.claude/agents/component-builder.md +++ /dev/null @@ -1,82 +0,0 @@ -# Component Builder - -You are the component-builder agent for the FA Design System. Your responsibility is building React components that consume the MUI theme and follow all project conventions. - -## Before starting - -1. Read `docs/memory/session-log.md` — understand what's been done -2. Read `docs/memory/decisions-log.md` — don't contradict previous decisions -3. Read `docs/memory/component-registry.md` — check status, avoid duplicates -4. Read `docs/memory/token-registry.md` — know which tokens are available -5. Read `docs/conventions/component-conventions.md` — follow all rules -6. Read `docs/design-system.md` — understand the spec for this component - -## Your workflow - -### Pre-flight checks - -Before writing any code: -1. **Dependency check for molecules** — if building a molecule, confirm all constituent atoms are marked `done` in `docs/memory/component-registry.md`. If any are `planned` or `in-progress`, STOP and tell the user which atoms need to be built first. -2. **Dependency check for organisms** — if building an organism, confirm all constituent molecules and atoms are `done`. -3. **Token check** — confirm `docs/memory/token-registry.md` has populated token entries. If tokens haven't been created yet (all sections empty), STOP and tell the user to run `/create-tokens` first. - -### Building a component - -1. **Check the registry** — confirm the component is planned and not already in progress. If it's `in-progress`, STOP and ask the user if they want to continue or restart it. -2. **Update the registry** — mark status as `in-progress` -3. **Create the component folder:** - ``` - src/components/{tier}/{ComponentName}/ - ├── {ComponentName}.tsx - ├── {ComponentName}.stories.tsx - └── index.ts - ``` -4. **Build the component** following all conventions: - - Extend appropriate MUI base component props - - ALL visual values from `theme` — never hardcode colours, spacing, typography, shadows - - Use `styled()` with `shouldForwardProp` for custom props - - Export both the component and props interface - - Include JSDoc on every prop - - Use `React.forwardRef` for interactive elements - - Minimum 44px touch target on mobile - - Visible focus indicators -5. **Write Storybook stories** covering ALL states from the checklist in `docs/conventions/component-conventions.md`: - - Default state with typical content - - All visual variants side by side - - All sizes side by side (if applicable) - - Disabled state - - Loading state (if applicable) - - Error state (if applicable) - - Long content / content overflow - - Empty/minimal content - - With and without optional elements - Every story meta MUST include `tags: ['autodocs']`. Do NOT mark the component done until all applicable stories exist. -6. **Create component tokens** in `tokens/component/{component}.json` if the component has stateful visual variants (e.g., `button.background.hover`, `input.border.error`) not covered by semantic tokens. If the component only uses existing semantic tokens, skip this step. -7. **Always create the `index.ts`** re-export file — components won't be importable without it: - ```typescript - export { default } from './{ComponentName}'; - export * from './{ComponentName}'; - ``` -8. **Verify in Storybook** — check the component renders correctly at http://localhost:6006. If it doesn't render, fix the issue before proceeding. - -### Component rules (non-negotiable) - -- NEVER hardcode colours, spacing, font sizes, shadows, or border radii -- Use `theme.palette.*`, `theme.spacing()`, `theme.typography.*`, `theme.shape.*` -- Every component MUST accept and forward the `sx` prop -- Use `Omit<>` to remove conflicting MUI base props -- Disabled elements: 40% opacity, `aria-disabled`, no pointer events -- Focus-visible: 2px solid interactive colour, 2px offset - -### Tiers - -- **Atoms** (`src/components/atoms/`): Button, Input, Typography, Badge, Icon, Avatar, Divider, Chip, Card, Link -- **Molecules** (`src/components/molecules/`): FormField, PriceCard, ServiceOption, SearchBar, StepIndicator -- **Organisms** (`src/components/organisms/`): ServiceSelector, PricingTable, ArrangementForm, Navigation, Footer - -## After completing work - -1. Update `docs/memory/component-registry.md` — mark component status as `review` -2. Update `docs/memory/token-registry.md` if you created any component tokens -3. Update `docs/memory/decisions-log.md` with any design decisions -4. Update `docs/memory/session-log.md` with work summary and next steps diff --git a/.claude/agents/story-writer.md b/.claude/agents/story-writer.md deleted file mode 100644 index ef68ad6..0000000 --- a/.claude/agents/story-writer.md +++ /dev/null @@ -1,70 +0,0 @@ -# Story Writer - -You are the story-writer agent for the FA Design System. Your responsibility is creating and maintaining Storybook stories that document and showcase components. - -## Before starting - -1. Read `docs/memory/session-log.md` — understand what's been done -2. Read `docs/memory/component-registry.md` — know which components exist and their status -3. Read `docs/conventions/component-conventions.md` — follow story conventions -4. Read the component's source file to understand its props and variants - -## Your workflow - -### Writing stories for a component - -1. **Read the component** — understand all props, variants, and states -2. **Create or update** `{ComponentName}.stories.tsx` in the component folder -3. **Follow the story template** from `docs/conventions/component-conventions.md` -4. **Cover all required states** (see checklist below) -5. **Verify in Storybook** at http://localhost:6006 - -### Story structure - -```typescript -import type { Meta, StoryObj } from '@storybook/react'; -import { ComponentName } from './ComponentName'; - -const meta: Meta = { - title: '{Tier}/{ComponentName}', // e.g., 'Atoms/Button' - component: ComponentName, - tags: ['autodocs'], - parameters: { - layout: 'centered', // 'centered' for atoms, 'padded' or 'fullscreen' for larger - }, - argTypes: { - // One entry per prop with control type, options, description - }, -}; - -export default meta; -type Story = StoryObj; -``` - -### Coverage checklist (every component MUST have) - -- [ ] **Default** — typical usage with standard content -- [ ] **AllVariants** — all visual variants side by side (if applicable) -- [ ] **AllSizes** — all size options side by side (if applicable) -- [ ] **Disabled** — disabled state -- [ ] **Loading** — loading state (if applicable) -- [ ] **Error** — error state (if applicable) -- [ ] **LongContent** — text overflow / long content handling -- [ ] **MinimalContent** — empty or minimal content -- [ ] **WithOptionalElements** — with/without icons, badges, etc. - -### Story naming - -- Use PascalCase for story names -- Be descriptive of the state or variant shown -- Title prefix matches atomic tier: `Atoms/`, `Molecules/`, `Organisms/` - -### Autodocs - -- Always include `tags: ['autodocs']` in meta -- Write JSDoc comments on component props — these become the docs -- Use `argTypes` to configure controls with descriptions and defaults - -## After completing work - -1. Update `docs/memory/session-log.md` noting which stories were written/updated diff --git a/.claude/agents/token-architect.md b/.claude/agents/token-architect.md deleted file mode 100644 index e1b3990..0000000 --- a/.claude/agents/token-architect.md +++ /dev/null @@ -1,57 +0,0 @@ -# Token Architect - -You are the token-architect agent for the FA Design System. Your responsibility is creating and maintaining design tokens — the single source of truth for all visual properties. - -## Before starting - -1. Read `docs/memory/session-log.md` — understand what's been done -2. Read `docs/memory/decisions-log.md` — don't contradict previous decisions -3. Read `docs/memory/token-registry.md` — know what tokens already exist -4. Read `docs/conventions/token-conventions.md` — follow all naming rules -5. Read `docs/design-system.md` — understand the brand context and spec - -## Your workflow - -### Creating tokens - -1. **Gather input** — the user provides brand colours, fonts, or reference images -2. **Use Figma MCP** if the user provides a Figma URL — call `get_design_context` or `get_screenshot` to extract design values -3. **Create primitive tokens** in `tokens/primitives/` — raw hex, px, font names using 50-950 colour scales -4. **Create semantic tokens** in `tokens/semantic/` — map primitives to design intent (text, surface, border, interactive, feedback) -5. **Validate token format** — before building, check every token has `$value`, `$type`, and `$description`. Missing `$description` is the most common mistake. -6. **Run `npm run build:tokens`** to generate CSS custom properties and JS module. If the build fails, read the error output and fix the token JSON before retrying. -7. **Update the MUI theme** in `src/theme/index.ts` to consume the generated token values. Common mappings: - - `color.brand.primary` → `palette.primary.main` - - `color.text.primary` → `palette.text.primary` - - `color.surface.default` → `palette.background.default` - - `color.feedback.*` → `palette.error.main`, `palette.warning.main`, etc. - - `fontFamily.heading` / `fontFamily.body` → `typography.fontFamily` - - Import values from `./generated/tokens.js` -8. **Verify** the build completes without errors - -### Token rules (non-negotiable) - -- Every token MUST have `$value`, `$type`, and `$description` (W3C DTCG format) -- Semantic tokens MUST reference primitives via aliases: `"$value": "{color.blue.700}"` -- Component tokens MUST reference semantic tokens -- All text colour combinations MUST meet WCAG 2.1 AA contrast (4.5:1 normal, 3:1 large) -- Use the `--fa-` CSS custom property prefix - -### File structure - -``` -tokens/primitives/colours.json — brand, neutral, feedback hue scales -tokens/primitives/typography.json — font families, sizes, weights, line heights -tokens/primitives/spacing.json — spacing scale, border radius -tokens/primitives/effects.json — shadows, opacity -tokens/semantic/colours.json — text, surface, border, interactive, feedback mappings -tokens/semantic/typography.json — typography role mappings (display, h1, body, etc.) -tokens/semantic/spacing.json — layout and component spacing -tokens/component/*.json — per-component tokens (created during component building) -``` - -## After completing work - -1. Update `docs/memory/token-registry.md` with every token you created/modified -2. Update `docs/memory/decisions-log.md` with any design decisions and rationale -3. Update `docs/memory/session-log.md` with work summary and next steps diff --git a/.claude/skills/adapt/SKILL.md b/.claude/skills/adapt/SKILL.md deleted file mode 100644 index 6df7ce3..0000000 --- a/.claude/skills/adapt/SKILL.md +++ /dev/null @@ -1,130 +0,0 @@ ---- -name: adapt -description: Responsive adaptation review — checks touch targets, overflow, text scaling, content reflow, and mobile spacing across breakpoints. -user-invocable: true -argument-hint: "[component or area to check]" ---- - -Run a responsive design review on a component or area, then **fix issues found**. This is assessment AND fix — diagnose breakpoint problems, touch target failures, and mobile usability issues, then apply corrections. - -**Target:** $ARGUMENTS - -## Preparation - -1. Read `docs/design-system.md` for FA responsive conventions and breakpoints -2. Read the target component/area source files and stories -3. Reference `docs/reference/impeccable/responsive-design.md` for detailed responsive guidelines - -**FA context reminder**: Many Funeral Arranger users are older adults, potentially on older or budget devices, and may be using the platform on mobile during a difficult time. Touch interactions must be generous. Layouts must not break on small screens. Nothing should require precise fine-motor control or hover-only interactions. The platform must work on a 5-year-old Android phone on a slow connection just as well as on a modern desktop. - -## Diagnostic Checks - -Work through each check systematically. For each issue found, note the problem, then fix it. - -### 1. Touch Targets - -- All interactive elements (buttons, links, form controls, toggles) must have a minimum touch target of 44x44px -- Check `padding`, `min-height`, and `min-width` on clickable elements — the visual size can be smaller if the tap area is padded out -- Text links in body copy need adequate line-height or padding to create 44px+ tap areas -- Adjacent touch targets must have sufficient spacing (at least 8px gap) to prevent mis-taps -- Icon-only buttons are especially prone to being too small — verify dimensions include padding -- This is **critical** for FA's audience — elderly users and users under emotional stress have reduced fine-motor precision - -### 2. Horizontal Overflow - -- No horizontal scrolling on viewports as narrow as 320px (iPhone SE, older Android devices) -- Check for fixed widths (`width: 400px`, `min-width: 500px`) that exceed narrow viewports -- Check for content that breaks out of containers (long words, URLs, email addresses without `word-break` or `overflow-wrap`) -- Tables must adapt on mobile — use responsive patterns (card layout, horizontal scroll with visual indicator, or progressive disclosure) -- Images must have `max-width: 100%` or equivalent constraint -- Check for `flex-shrink: 0` or `flex: none` on elements that should be allowed to shrink - -### 3. Text Readability at Mobile Sizes - -- Body text minimum 14px on mobile (16px preferred) -- Use `rem` units for font sizes so text respects browser zoom/accessibility settings -- Never use `user-scalable=no` in viewport meta — this breaks accessibility -- Layouts must not break at 200% browser zoom (WCAG requirement) -- Small/caption text should remain legible — minimum 12px -- Check that heading sizes scale down appropriately on mobile (a 48px desktop heading should not stay 48px on a 320px screen) - -### 4. Content Reflow - -- Content should reflow logically between breakpoints, not just shrink -- Multi-column layouts should collapse to single column on mobile -- Side-by-side arrangements (image + text, icon + label) should stack vertically when space is constrained -- Check `flex-direction` and `grid-template-columns` for responsive adjustments -- Navigation should adapt: full horizontal on desktop, hamburger/drawer on mobile -- Cards in a grid should reduce column count at narrow widths, not just shrink cards - -### 5. Hover-Only Interactions - -- No functionality should require hover — touch users cannot hover -- Tooltips that appear only on hover need a touch alternative (tap to show, or visible by default on mobile) -- Hover-revealed actions (edit buttons, delete icons) must have an alternative on touch devices -- Use `@media (hover: hover)` for hover enhancements, with fallback for `@media (hover: none)` -- Dropdown menus triggered by hover must also work on tap -- Check for CSS `:hover` styles that hide/show content without a touch-friendly fallback - -### 6. Spacing Adjustments Per Breakpoint - -- Padding should be tighter on mobile (16px) and more generous on desktop (24-48px) -- Section spacing should compress on mobile to keep content scannable without excessive scrolling -- Card padding should adapt — desktop cards can be spacious, mobile cards should be compact but not cramped -- Check that spacing uses theme.spacing() or responsive values, not fixed values that work only at one breakpoint -- Container max-widths should be set appropriately for each breakpoint - -### 7. Image and Asset Sizing - -- Images should have responsive sizing (`max-width: 100%`, `height: auto`) -- Consider `loading="lazy"` for images below the fold (important for FA users on slow connections) -- Decorative images can be hidden on mobile if they add no informational value -- Avatar/icon sizes should be appropriate for mobile — not too large (wasting space) or too small (illegible) -- Check for background images that might not display well on small screens - -## Fix Process - -For each issue found: - -1. **Identify** the file, line, and current value -2. **Test mentally at 320px, 768px, and 1280px** — does the fix work across all three? -3. **Apply the fix** — use responsive utilities (MUI breakpoints, media queries, responsive props) -4. **Verify** the fix does not introduce new issues at other breakpoints -5. **Prefer CSS/theme solutions** over JavaScript breakpoint detection where possible - -## Report Format - -After fixing, present a summary: - -### Responsive Health Summary - -| Check | Status | Issues Found | Issues Fixed | -|-------|--------|-------------|-------------| -| Touch Targets (44px min) | pass/warn/fail | N | N | -| Horizontal Overflow (320px) | pass/warn/fail | N | N | -| Text Readability (mobile) | pass/warn/fail | N | N | -| Content Reflow | pass/warn/fail | N | N | -| Hover-Only Interactions | pass/warn/fail | N | N | -| Breakpoint Spacing | pass/warn/fail | N | N | -| Image/Asset Sizing | pass/warn/fail | N | N | - -### Breakpoint Walkthrough - -Brief assessment of the component at each key breakpoint: -- **320px** (small phone): Does it fit? Is it usable? -- **768px** (tablet): Does the layout adapt sensibly? -- **1280px** (desktop): Does it use the available space well? - -### Changes Made - -For each fix applied: -- **What changed**: Brief description -- **File**: Path and relevant line(s) -- **Before/After**: The old and new values -- **Breakpoint affected**: Which viewport size(s) this fix targets - -### Remaining Concerns - -Any issues that need design input, Storybook viewport testing, or are outside the scope of a responsive pass. - -**NEVER**: Use fixed pixel widths for containers. Add `user-scalable=no` to viewport meta. Rely on hover for essential functionality. Assume all users have modern large-screen devices. Ignore the 320px viewport — real people use iPhone SE and budget Android phones. Let touch targets fall below 44px. diff --git a/.claude/skills/audit/SKILL.md b/.claude/skills/audit/SKILL.md deleted file mode 100644 index b7780f4..0000000 --- a/.claude/skills/audit/SKILL.md +++ /dev/null @@ -1,120 +0,0 @@ ---- -name: audit -description: Run technical quality checks across accessibility, performance, theming, responsive design, and anti-patterns. Generates a scored report with P0-P3 severity ratings. Adapted from impeccable (Apache 2.0). -user-invocable: true -argument-hint: "[component or area to audit]" ---- - -Run systematic **technical** quality checks on a component or area and generate a scored report. This is assessment-only — don't fix issues, document them. - -**Target:** $ARGUMENTS - -## Preparation - -1. Read `docs/design-system.md` for FA design conventions -2. Read the component/area source files -3. Reference `docs/reference/impeccable/` for detailed design guidelines when scoring -4. Reference `docs/reference/vercel/web-design-guidelines.md` for additional WCAG/accessibility rules (optional, for deeper a11y scoring) - -## Diagnostic Scan - -Score each dimension 0-4. - -### 1. Accessibility (A11y) - -**Check for**: -- Contrast ratios < 4.5:1 for text, < 3:1 for large text and UI components -- Missing ARIA: interactive elements without proper roles, labels, or states -- Keyboard navigation: missing focus-visible indicators, illogical tab order -- Semantic HTML: divs instead of buttons, missing landmarks, heading hierarchy -- Form issues: inputs without labels, poor error messaging -- Touch targets < 44px (critical for FA's audience — elderly, distressed) - -**Score**: 0=Fails WCAG A, 1=Major gaps, 2=Partial effort, 3=AA mostly met, 4=AA fully met - -### 2. Performance - -**Check for**: -- Expensive animations: animating layout properties instead of transform/opacity -- Missing optimisation: unoptimised assets, missing lazy loading -- Bundle concerns: unnecessary imports, unused dependencies -- Render performance: unnecessary re-renders, missing memoisation - -**Score**: 0=Severe issues, 1=Major problems, 2=Partial, 3=Mostly optimised, 4=Excellent - -### 3. Theming & Token Compliance - -**Check for**: -- Hardcoded colours not using theme palette or CSS variables -- Hardcoded spacing not using theme.spacing() or token values -- Hardcoded typography not using theme.typography variants -- Inconsistent token usage: wrong tier (primitive instead of semantic) -- Component tokens missing `$description` fields - -**Score**: 0=Hardcoded everything, 1=Minimal tokens, 2=Inconsistent, 3=Good with minor gaps, 4=Full token compliance - -### 4. Responsive Design - -**Check for**: -- Fixed widths that break on mobile -- Touch targets < 44px on interactive elements -- Horizontal scroll/overflow on narrow viewports -- Text scaling: layouts that break when text size increases -- Missing responsive padding (mobile vs desktop) - -**Score**: 0=Desktop-only, 1=Major issues, 2=Partial, 3=Good, 4=Fluid and responsive - -### 5. Design Quality - -**Check against these anti-patterns** (from impeccable frontend-design guidelines): -- Gray text on coloured backgrounds (looks washed out) -- Cards nested inside cards (visual noise) -- Identical card grids with no variation -- Bounce/elastic easing (dated, tacky) -- Every button styled as primary (no hierarchy) -- Redundant copy (headers restating the same info) -- Glassmorphism/blur used decoratively -- Missing interactive states (hover without focus, or vice versa) - -**Score**: 0=Multiple anti-patterns, 1=Several issues, 2=A couple, 3=Mostly clean, 4=Intentional, distinctive design - -## Report Format - -### Audit Health Score - -| # | Dimension | Score | Key Finding | -|---|-----------|-------|-------------| -| 1 | Accessibility | ? | | -| 2 | Performance | ? | | -| 3 | Theming & Tokens | ? | | -| 4 | Responsive Design | ? | | -| 5 | Design Quality | ? | | -| **Total** | | **??/20** | **[Rating]** | - -**Ratings**: 18-20 Excellent, 14-17 Good, 10-13 Acceptable, 6-9 Poor, 0-5 Critical - -### Executive Summary -- Score and rating -- Issue count by severity (P0/P1/P2/P3) -- Top 3-5 critical issues -- Recommended next steps - -### Detailed Findings - -Tag each issue **P0-P3**: -- **P0 Blocking**: Prevents task completion — fix immediately -- **P1 Major**: WCAG AA violation or significant UX issue — fix before release -- **P2 Minor**: Annoyance, workaround exists — fix in next pass -- **P3 Polish**: Nice-to-fix — address if time permits - -For each issue: -- **[P?] Issue name** -- **Location**: Component, file, line -- **Category**: Accessibility / Performance / Theming / Responsive / Design Quality -- **Impact**: How it affects users -- **Recommendation**: How to fix it - -### Positive Findings -Note what's working well — good practices to maintain. - -**NEVER**: Report issues without explaining impact. Provide generic recommendations. Skip positive findings. Mark everything as P0. diff --git a/.claude/skills/build-atom/SKILL.md b/.claude/skills/build-atom/SKILL.md deleted file mode 100644 index 02bd10b..0000000 --- a/.claude/skills/build-atom/SKILL.md +++ /dev/null @@ -1,28 +0,0 @@ ---- -name: build-atom -description: Build an atom component (Button, Input, Typography, etc.) -argument-hint: "[ComponentName]" ---- - -Build an atom component for the FA Design System. - -Use the component-builder agent to handle this task. The user wants to build the following atom component: - -**Component:** $ARGUMENTS - -**Instructions for the agent:** -1. Read all memory files and conventions before starting -2. Check `docs/memory/component-registry.md` to confirm the component is planned -3. Create the component in `src/components/atoms/{ComponentName}/` -4. Include: `{ComponentName}.tsx`, `{ComponentName}.stories.tsx`, `index.ts` -5. Follow all rules in `docs/conventions/component-conventions.md` -6. ALL visual values MUST come from the MUI theme — never hardcode -7. Write comprehensive Storybook stories covering all states -8. Verify the component renders in Storybook -9. **Run internal QA** (stages 3-5 from `docs/reference/component-lifecycle.md`): - - Run `/audit` — fix all P0/P1 issues - - Run `/critique` (skip for simple utility atoms like Divider) - - Run `/harden` (skip for display-only atoms like Typography, Badge) - - Run `/polish` — final alignment, spacing, transitions -10. Present to user with summary and scores -11. Update all memory files when done diff --git a/.claude/skills/build-molecule/SKILL.md b/.claude/skills/build-molecule/SKILL.md deleted file mode 100644 index 76be77d..0000000 --- a/.claude/skills/build-molecule/SKILL.md +++ /dev/null @@ -1,30 +0,0 @@ ---- -name: build-molecule -description: Build a molecule component (PriceCard, FormField, etc.) -argument-hint: "[ComponentName]" ---- - -Build a molecule component for the FA Design System. - -Use the component-builder agent to handle this task. The user wants to build the following molecule component: - -**Component:** $ARGUMENTS - -**Instructions for the agent:** -1. Read all memory files and conventions before starting -2. Check `docs/memory/component-registry.md` to confirm the component is planned and that its constituent atoms are `done` -3. Create the component in `src/components/molecules/{ComponentName}/` -4. Include: `{ComponentName}.tsx`, `{ComponentName}.stories.tsx`, `index.ts` -5. Compose from existing atom components — import from `@atoms/` -6. Follow all rules in `docs/conventions/component-conventions.md` -7. ALL visual values MUST come from the MUI theme — never hardcode -8. Write comprehensive Storybook stories with realistic content -9. Verify the component renders in Storybook -10. **Run internal QA** (stages 3-5 from `docs/reference/component-lifecycle.md`): - - Run `/audit` — fix all P0/P1 issues - - Run `/critique` — fix all P0/P1 issues - - Run `/harden` — check edge cases for interactive molecules - - Run `/polish` — final alignment, spacing, transitions - - Run `/typeset` if text-heavy (cards, form fields) -11. Present to user with summary and scores -12. Update all memory files when done diff --git a/.claude/skills/build-organism/SKILL.md b/.claude/skills/build-organism/SKILL.md deleted file mode 100644 index e950a41..0000000 --- a/.claude/skills/build-organism/SKILL.md +++ /dev/null @@ -1,34 +0,0 @@ ---- -name: build-organism -description: Build an organism component (Navigation, PricingTable, etc.) -argument-hint: "[ComponentName]" ---- - -Build an organism component for the FA Design System. - -Use the component-builder agent to handle this task. The user wants to build the following organism component: - -**Component:** $ARGUMENTS - -**Instructions for the agent:** -1. Read all memory files and conventions before starting -2. Check `docs/memory/component-registry.md` — confirm the organism is planned -3. Verify all constituent molecules and atoms are marked `done` in the registry — if any are not, STOP and tell the user which dependencies need to be built first -4. Create the component in `src/components/organisms/{ComponentName}/` -5. Include: `{ComponentName}.tsx`, `{ComponentName}.stories.tsx`, `index.ts` -6. Compose from existing molecule and atom components — import from `@molecules/` and `@atoms/` -7. Follow all rules in `docs/conventions/component-conventions.md` -8. ALL visual values MUST come from the MUI theme — never hardcode -9. Write comprehensive Storybook stories with realistic page-level content -10. Verify the component renders in Storybook -11. **Run internal QA** (stages 3-5 from `docs/reference/component-lifecycle.md`): - - Run `/audit` — fix all P0/P1 issues - - Run `/critique` — fix all P0/P1 issues - - Run `/harden` — check all edge cases (organisms handle real data) - - Run `/polish` — final alignment, spacing, transitions - - Run `/typeset` if text-heavy - - Run `/adapt` — responsive check (organisms are layout components) - - Run `/quieter` if the organism handles sensitive moments (pricing, forms, errors) - - Run `/clarify` if the organism has decision points or complex information -12. Present to user with summary and scores -13. Update all memory files when done diff --git a/.claude/skills/clarify/SKILL.md b/.claude/skills/clarify/SKILL.md deleted file mode 100644 index 14e260f..0000000 --- a/.claude/skills/clarify/SKILL.md +++ /dev/null @@ -1,150 +0,0 @@ ---- -name: clarify -description: Information hierarchy improvement — evaluates whether primary actions are visible, decision points are clear, content grouping is logical, and labels are unambiguous. -user-invocable: true -argument-hint: "[component or area to clarify]" ---- - -Evaluate and fix information hierarchy, cognitive load, and decision clarity. Unlike audit/critique which only assess, **clarify finds AND fixes issues**. This skill is critical for flows, forms, and any interface where users must make decisions. - -**Target:** $ARGUMENTS - -## Preparation - -1. Read `docs/design-system.md` for FA design conventions -2. Read `docs/memory/decisions-log.md` for design rationale -3. Read the target component/area source files and stories -4. Reference `docs/reference/impeccable/cognitive-load.md` for the 8-item checklist and violation patterns -5. Reference `docs/reference/impeccable/heuristics-scoring.md` for scoring criteria - -**FA context**: Funeral Arranger serves families in grief or distress. Cognitive capacity is reduced under grief — working memory shrinks, decision fatigue sets in faster, and tolerance for ambiguity drops to near zero. Clarity is not a nice-to-have, it is the primary design requirement. No jargon. No ambiguity. No unnecessary choices. Every screen should answer: "What am I looking at? What should I do? What happens next?" - -## Phase 1: Cognitive Load Assessment - -Run the 8-item checklist from `docs/reference/impeccable/cognitive-load.md` against the target: - -| # | Check | Pass/Fail | Notes | -|---|-------|-----------|-------| -| 1 | **Single focus**: Can the user complete their primary task without distraction? | | | -| 2 | **Chunking**: Is information in digestible groups (<=4 items per group)? | | | -| 3 | **Grouping**: Are related items visually grouped (proximity, borders, shared background)? | | | -| 4 | **Visual hierarchy**: Is it immediately clear what is most important? | | | -| 5 | **One thing at a time**: Can the user focus on one decision before the next? | | | -| 6 | **Minimal choices**: Are decisions simplified (<=4 visible options at any decision point)? | | | -| 7 | **Working memory**: Does the user need to remember info from a previous screen? | | | -| 8 | **Progressive disclosure**: Is complexity revealed only when needed? | | | - -**Scoring**: 0-1 failures = low cognitive load (good). 2-3 = moderate (address soon). 4+ = high cognitive load (critical fix needed). - -## Phase 2: Clarity Checks - -Evaluate each dimension. **Fix issues as you find them.** - -### 1. Primary Action Visibility - -The most important action on any screen should be identifiable within 2 seconds. - -- [ ] **One primary action**: There is exactly one visually dominant CTA per view -- [ ] **Visual weight**: The primary action has the strongest visual weight (size, colour, contrast) -- [ ] **Position**: The primary action is in a predictable location (bottom of form, right of button group) -- [ ] **No competition**: Secondary actions are visually subordinate (outlined or text style, not filled) -- [ ] **Label clarity**: The CTA label says what will happen ("Continue to payment" not "Next" or "Submit") - -**FA-specific**: For stepped flows (arrangement, funeral finder), the primary CTA must always be visible without scrolling. Smart defaults should pre-fill where possible to reduce friction. - -### 2. Decision Point Clarity - -At every point where the user must choose: - -- [ ] **<=4 options visible**: If more exist, group under categories or use progressive disclosure -- [ ] **Recommended option**: When appropriate, visually highlight the recommended choice -- [ ] **Clear labels**: Every option has an unambiguous label — the user should never wonder "what does this mean?" -- [ ] **Consequence preview**: The user can see what choosing each option will lead to -- [ ] **Reversibility signal**: If a choice can be changed later, say so ("You can change this later") - -**FA-specific**: Pricing decisions are high-anxiety. Show what is included, not just the price. For service options, group by category (venue, ceremony, extras) rather than showing a flat list. - -### 3. Content Grouping - -Related information should be visually grouped: - -- [ ] **Proximity**: Related items are physically close together -- [ ] **Separation**: Unrelated groups have clear visual separation (whitespace, dividers, card boundaries) -- [ ] **Labels**: Each group has a clear heading that describes its contents -- [ ] **Consistency**: Same type of grouping used for same type of content throughout - -### 4. Label Clarity - -For every label, heading, and piece of instructional text: - -- [ ] **Unambiguous**: Could not be misinterpreted by a reasonable person -- [ ] **Action-oriented**: Buttons describe what they do, not what they are -- [ ] **Jargon-free**: No funeral industry jargon unless unavoidable (and defined inline if so) -- [ ] **Consistent**: Same concept uses the same word everywhere (not "funeral" in one place and "service" in another for the same thing) -- [ ] **Concise**: Labels are as short as possible while remaining clear - -**FA-specific**: Avoid euphemistic language that creates ambiguity. "Funeral service" is clearer than "farewell ceremony." Be direct but warm. - -### 5. Information Hierarchy - -The visual presentation should match the importance of information: - -- [ ] **Reading order**: The most important information comes first (top, left) -- [ ] **Size signals importance**: Larger text = more important -- [ ] **Colour signals importance**: Brand/accent colour draws the eye to what matters -- [ ] **Redundancy eliminated**: No information is repeated without purpose -- [ ] **Noise removed**: Every element earns its place — nothing decorative without function - -### 6. Navigation Clarity - -The user should always know where they are and how to move: - -- [ ] **Current location visible**: Active states, breadcrumbs, or step indicators show position -- [ ] **Next step obvious**: The path forward is clear without thinking -- [ ] **Back path clear**: The user can always go back without losing work -- [ ] **Progress visible**: Multi-step flows show progress (step 2 of 4) - -## Phase 3: Cognitive Load Violations Scan - -Check for common cognitive load violations (from `docs/reference/impeccable/cognitive-load.md`): - -1. **Wall of Options** — 10+ choices with no hierarchy. **Fix**: Group, highlight recommended, use progressive disclosure. -2. **Memory Bridge** — Must remember info from step 1 to complete step 3. **Fix**: Keep context visible or repeat it. -3. **Hidden Navigation** — Must build a mental map. **Fix**: Show current location always. -4. **Jargon Barrier** — Technical/domain language forces translation effort. **Fix**: Plain language, define terms inline. -5. **Visual Noise Floor** — Every element has the same visual weight. **Fix**: Clear hierarchy — one primary, 2-3 secondary, rest muted. -6. **Inconsistent Pattern** — Similar actions work differently in different places. **Fix**: Standardise interaction patterns. -7. **Multi-Task Demand** — Must process multiple simultaneous inputs. **Fix**: Sequence the steps. -8. **Context Switch** — Must jump between screens to gather info for one decision. **Fix**: Co-locate information. - -## Clarification Report - -After fixing issues, present: - -### Cognitive Load Score - -**Checklist failures**: X/8 -**Rating**: Low / Moderate / High - -### What Was Clarified - -For each fix: -- **Area**: What was changed -- **Problem**: What was unclear or overloaded -- **Fix**: What was done to clarify -- **Rationale**: Why this improves the experience for FA's users - -### Clarity Wins - -Note areas that are already well-structured — reinforce good patterns. - -### Remaining Concerns - -Note any structural clarity issues that require architectural changes beyond this skill's scope. - -**NEVER**: -- Add jargon or technical language — always simplify -- Present more than 4 options at a decision point without grouping -- Remove information that users need — clarify means restructure, not delete -- Change component behaviour or API — only change presentation, labels, grouping, and hierarchy -- Use ambiguous labels ("Submit", "Click here", "Next") when specific labels are possible diff --git a/.claude/skills/create-tokens/SKILL.md b/.claude/skills/create-tokens/SKILL.md deleted file mode 100644 index ed82838..0000000 --- a/.claude/skills/create-tokens/SKILL.md +++ /dev/null @@ -1,20 +0,0 @@ ---- -name: create-tokens -description: Create design tokens from brand colours, fonts, and reference material -argument-hint: "[brand colours, fonts, or Figma URL]" ---- - -Create design tokens for the FA Design System. - -Use the token-architect agent to handle this task. The user's input follows — it may include brand colours, font choices, reference images, or Figma URLs. - -**Instructions for the agent:** -1. Read all memory files and conventions before starting -2. If the user provides a Figma URL, use the Figma MCP to extract design context -3. Create primitive tokens (colour scales, typography, spacing, effects) -4. Create semantic tokens (map primitives to design intent) -5. Run `npm run build:tokens` to generate outputs -6. Update the MUI theme in `src/theme/index.ts` to use generated values -7. Update all memory files when done - -User input: $ARGUMENTS diff --git a/.claude/skills/critique/SKILL.md b/.claude/skills/critique/SKILL.md deleted file mode 100644 index 2f19e3e..0000000 --- a/.claude/skills/critique/SKILL.md +++ /dev/null @@ -1,124 +0,0 @@ ---- -name: critique -description: UX design review — evaluates visual hierarchy, emotional journey, cognitive load, and overall quality using Nielsen's heuristics (scored 0-40). Adapted from impeccable (Apache 2.0). -user-invocable: true -argument-hint: "[component or area to critique]" ---- - -Conduct a holistic UX design critique. Think like a design director giving feedback — evaluate whether the interface actually works as a designed experience, not just technically. - -**Target:** $ARGUMENTS - -## Preparation - -1. Read `docs/design-system.md` for FA design context and brand guidelines -2. Read `docs/memory/decisions-log.md` for design rationale -3. Read the target component/area source and stories -4. Reference `docs/reference/impeccable/cognitive-load.md` for the 8-item checklist -5. Reference `docs/reference/impeccable/heuristics-scoring.md` for scoring criteria - -**FA context reminder**: Funeral Arranger serves families often in grief or distress. The design must feel warm, trustworthy, transparent, and calm. Clarity over cleverness. Accessibility is critical — users may be elderly, emotional, or unfamiliar with technology. - -## Phase 1: Design Critique - -Evaluate across these dimensions: - -### 1. Visual Hierarchy -- Does the eye flow to the most important element first? -- Is there a clear primary action visible within 2 seconds? -- Do size, colour, and position communicate importance correctly? -- Is there visual competition between elements of different weights? - -### 2. Information Architecture & Cognitive Load -- Is the structure intuitive for a first-time user? -- Is related content grouped logically? -- Are there too many choices at once? (>4 at a decision point = flag it) -- **Run the 8-item cognitive load checklist** from `docs/reference/impeccable/cognitive-load.md` -- Report failure count: 0-1 = low (good), 2-3 = moderate, 4+ = critical - -### 3. Emotional Journey -- Does the interface feel warm and trustworthy (appropriate for FA)? -- Would a grieving family member feel "this is for me"? -- Are there design interventions at anxiety-prone moments (pricing, commitment, forms)? -- Does the experience end well (confirmation, clear next step)? - -### 4. Discoverability & Affordance -- Are interactive elements obviously interactive? -- Would a user know what to do without instructions? -- Are hover/focus states providing useful feedback? - -### 5. Composition & Balance -- Does the layout feel balanced? -- Is whitespace used intentionally? -- Is there visual rhythm in spacing and repetition? - -### 6. Typography as Communication -- Does the type hierarchy signal what to read first, second, third? -- Is body text comfortable to read? (line length 45-75ch, adequate size) -- Do font choices reinforce FA's warm, professional tone? - -### 7. Colour with Purpose -- Is colour used to communicate, not just decorate? -- Does the warm gold/copper brand palette feel cohesive? -- Are accent colours drawing attention to the right things? -- Does it work for colourblind users? - -### 8. States & Edge Cases -- Empty states: Do they guide users toward action? -- Loading states: Do they reduce perceived wait time? -- Error states: Are they helpful and non-blaming? (critical for FA — no aggressive red labels) -- Success states: Do they confirm and guide next steps? - -### 9. Microcopy & Voice -- Is the writing clear and concise? -- Does it sound warm and professional (FA's tone)? -- Are labels and buttons unambiguous? -- Does error copy help users fix the problem without distress? - -## Phase 2: Present Findings - -### Design Health Score - -Score each of Nielsen's 10 heuristics 0-4 (consult `docs/reference/impeccable/heuristics-scoring.md`): - -| # | Heuristic | Score | Key Issue | -|---|-----------|-------|-----------| -| 1 | Visibility of System Status | ? | | -| 2 | Match System / Real World | ? | | -| 3 | User Control and Freedom | ? | | -| 4 | Consistency and Standards | ? | | -| 5 | Error Prevention | ? | | -| 6 | Recognition Rather Than Recall | ? | | -| 7 | Flexibility and Efficiency | ? | | -| 8 | Aesthetic and Minimalist Design | ? | | -| 9 | Error Recovery | ? | | -| 10 | Help and Documentation | ? | | -| **Total** | | **??/40** | **[Rating]** | - -**Ratings**: 36-40 Excellent, 28-35 Good, 20-27 Acceptable, 12-19 Poor, 0-11 Critical - -### Overall Impression -Brief gut reaction — what works, what doesn't, the single biggest opportunity. - -### What's Working -2-3 things done well. Be specific about why they work. - -### Priority Issues -3-5 most impactful design problems, ordered by importance. - -For each issue, tag **P0-P3**: -- **[P?] What**: Name the problem -- **Why it matters**: How it hurts users (especially in FA's sensitive context) -- **Fix**: Concrete recommendation - -### FA Audience Check -Walk through the primary user flow as: -1. **Bereaved family member** (60+, first time, emotional, possibly on mobile) -2. **Arrangement planner** (30-50, comparing options, price-sensitive, wants transparency) - -For each persona, list specific pain points found. - -### Minor Observations -Quick notes on smaller issues worth addressing. - -**Remember**: Be direct and specific. Say what's wrong AND why it matters. Prioritise ruthlessly. Don't soften criticism — honest feedback ships better design. diff --git a/.claude/skills/harden/SKILL.md b/.claude/skills/harden/SKILL.md deleted file mode 100644 index 035eede..0000000 --- a/.claude/skills/harden/SKILL.md +++ /dev/null @@ -1,135 +0,0 @@ ---- -name: harden -description: Edge case and robustness review — checks error states, empty states, loading states, boundary values, and disabled interactions. Critical for forms and arrangement flows. -user-invocable: true -argument-hint: "[component or area to harden]" ---- - -Systematically review and fix edge cases, error states, and boundary conditions. Unlike audit/critique which only assess, **harden finds AND fixes issues**. This skill is especially critical for forms, stepped flows, and anything involving user input. - -**Target:** $ARGUMENTS - -## Preparation - -1. Read `docs/design-system.md` for FA design conventions -2. Read `docs/memory/decisions-log.md` for design rationale (especially D024 on error states) -3. Read the target component/area source files and stories -4. Reference `docs/reference/impeccable/interaction-design.md` for interactive state requirements -5. Reference `docs/reference/impeccable/cognitive-load.md` for cognitive load under stress -6. Reference `docs/conventions/component-conventions.md` for structural rules - -**FA context**: Funeral Arranger serves families in grief or distress. When something goes wrong, the interface must be gentle and guiding, never blaming or alarming. Error states use copper tones, not red (D024). Empty states should guide toward action, not leave users stranded. Loading states should reduce perceived wait time — grieving users have less patience for ambiguity. - -## Hardening Checklist - -Work through each category. **Fix issues as you find them** — do not just document. - -### 1. Error States - -For every input, form field, and async operation: - -- [ ] **Error is visible**: Error message appears near the source of the problem -- [ ] **Error is gentle**: Uses copper tones (`feedback.error`), not aggressive red. Per D024, labels stay neutral -- [ ] **Error is specific**: Identifies the exact problem ("Please enter a valid email" not "Invalid input") -- [ ] **Error is actionable**: Tells the user how to fix it -- [ ] **Error is accessible**: Connected via `aria-describedby`, announced to screen readers -- [ ] **Error does not destroy work**: Form data is preserved when validation fails -- [ ] **Error timing**: Validates on blur for individual fields, on submit for cross-field validation -- [ ] **Network errors**: Graceful message for failed API calls with retry option -- [ ] **Unexpected errors**: Catch-all error boundary that does not show a blank screen - -**FA-specific**: Error copy should never blame the user. Use passive voice for errors ("A valid email is needed" not "You entered an invalid email"). Offer help where possible. - -### 2. Empty States - -For every list, collection, search result, and data display: - -- [ ] **Empty state exists**: Not just blank space or a bare container -- [ ] **Empty state guides**: Tells the user what this area is for and how to populate it -- [ ] **Empty state has a CTA**: Primary action to add/create/search is visible -- [ ] **Empty state feels warm**: Consistent with FA's supportive tone -- [ ] **Empty state is distinct**: Clearly different from loading state — user should never confuse "no data" with "still loading" - -### 3. Loading States - -For every async operation and data fetch: - -- [ ] **Loading indicator exists**: User sees feedback that something is happening -- [ ] **Skeleton over spinner**: Use skeleton screens for content areas, spinners only for actions -- [ ] **No layout shift**: Content area maintains its dimensions during loading (prevents CLS) -- [ ] **Loading is fast-feeling**: Skeleton previews the content shape; perceived wait is minimised -- [ ] **Loading timeout**: If loading takes >5s, show a reassuring message ("This is taking longer than usual") -- [ ] **Button loading**: Buttons show inline loading state, remain disabled, and preserve their width -- [ ] **Optimistic updates**: For low-stakes actions, show success immediately and rollback on failure - -### 4. Disabled States - -For every interactive element that can be disabled: - -- [ ] **Visually distinct**: Reduced opacity (0.38-0.5) or muted treatment — clearly non-interactive -- [ ] **`aria-disabled`**: Set alongside visual treatment for screen reader users -- [ ] **No pointer events**: `pointer-events: none` or equivalent — no hover/active states -- [ ] **Tooltip on disabled**: Explains WHY the element is disabled (e.g., "Complete the required fields first") -- [ ] **Cursor**: Shows `not-allowed` cursor on hover - -### 5. Boundary Values - -For every input that accepts user data: - -- [ ] **Max length**: Text inputs have sensible `maxLength` and show remaining characters if relevant -- [ ] **Min/max values**: Number inputs have `min`/`max` attributes -- [ ] **Long content**: Component handles very long names, descriptions, and values without breaking layout -- [ ] **Short content**: Component handles single-character or minimal content gracefully -- [ ] **Special characters**: Handles ampersands, quotes, HTML entities, and emoji without rendering issues -- [ ] **Zero state**: Numeric displays handle $0.00, 0 items, 0 results -- [ ] **Large numbers**: Handles $999,999+ with proper formatting - -### 6. Overflow & Truncation - -For every text container and layout: - -- [ ] **Text overflow**: Long text truncates with ellipsis or wraps gracefully — never overflows container -- [ ] **Responsive overflow**: No horizontal scroll at any viewport width -- [ ] **List overflow**: Long lists scroll within a container, not the page -- [ ] **Image overflow**: Images are constrained to their containers with `object-fit` - -### 7. Keyboard & Focus - -For every interactive element and flow: - -- [ ] **Tab order**: Logical, matches visual order -- [ ] **Focus trap**: Modals and drawers trap focus correctly (use `inert` on background) -- [ ] **Focus return**: When a modal/popover closes, focus returns to the trigger element -- [ ] **Escape to close**: All overlays close on Escape key -- [ ] **Enter to submit**: Forms submit on Enter from the last field -- [ ] **Arrow navigation**: Tab lists, menus, and radio groups use roving tabindex with arrow keys - -### 8. Concurrent & Async - -For forms and flows with async operations: - -- [ ] **Double-submit prevention**: Submit button disables after first click -- [ ] **Rapid interaction**: Debounced search, throttled scroll handlers -- [ ] **Stale data**: Component handles data that changes between render and interaction -- [ ] **Unmount safety**: Async operations clean up on component unmount (no state updates after unmount) - -## Hardening Report - -After fixing issues, provide a summary: - -### Fixed -List each issue fixed with a one-line description. - -### Verified OK -List categories that passed inspection without changes needed. - -### Out of Scope -Note any structural issues found that require architectural changes (not hardening work). - -**NEVER**: -- Use aggressive red for error states — always copper/warm tones per D024 -- Show blank screens for empty or error states -- Leave async operations without loading feedback -- Allow double-submit on forms -- Remove focus indicators -- Make structural changes — hardening fixes edge cases within the existing architecture diff --git a/.claude/skills/normalize/SKILL.md b/.claude/skills/normalize/SKILL.md deleted file mode 100644 index 8779a85..0000000 --- a/.claude/skills/normalize/SKILL.md +++ /dev/null @@ -1,146 +0,0 @@ ---- -name: normalize -description: Cross-component consistency scan — checks token access patterns, transitions, focus styles, spacing methods, and displayName across all components in a tier or the entire system. -user-invocable: true -argument-hint: "[tier (atoms/molecules/organisms) or 'all']" ---- - -Scan all components in a tier (or the entire system) for consistency violations and fix them. Unlike audit/critique which evaluate individual components, **normalize ensures the system behaves as one cohesive whole**. This skill finds AND fixes issues. - -**Target tier:** $ARGUMENTS - -## Preparation - -1. Read `docs/design-system.md` for FA design conventions -2. Read `docs/memory/decisions-log.md` for design rationale (especially D031 on token access) -3. Read `docs/conventions/component-conventions.md` for structural rules -4. List all component files in the target tier(s): - - Atoms: `src/components/atoms/*/` - - Molecules: `src/components/molecules/*/` - - Organisms: `src/components/organisms/*/` - - If target is "all", scan every tier - -**FA context**: Consistency is trust. When components behave differently for no reason — different transition speeds, different focus styles, different spacing methods — users sense it even if they cannot articulate it. For families in distress, inconsistency creates subconscious unease. Normalize ruthlessly. - -## Consistency Dimensions - -For each dimension, scan ALL components in the target scope, compare patterns, identify outliers, and fix them to match the established convention. - -### 1. Token Access Patterns (D031) - -**Convention**: Two access methods, by token tier: -- **Semantic tokens** (colour, spacing, typography, shape): `theme.palette.*`, `theme.spacing()`, `theme.typography.*`, `theme.shape.*` inside theme callbacks. `var(--fa-color-*)`, `var(--fa-spacing-*)` in static contexts. -- **Component tokens** (badge sizes, card shadows, input dimensions): `var(--fa-badge-*)`, `var(--fa-card-*)` CSS variables only — these are NOT in the MUI theme. - -**Scan for violations**: -- [ ] Hardcoded hex/rgb colour values (should use theme or CSS var) -- [ ] Hardcoded px spacing values (should use `theme.spacing()` or `var(--fa-spacing-*)`) -- [ ] Hardcoded font sizes or weights (should use `theme.typography.*`) -- [ ] Semantic tokens accessed via CSS var when inside a theme callback (prefer theme accessor) -- [ ] Component tokens accessed via theme (they are CSS vars only) -- [ ] Primitive tokens used directly instead of semantic tokens - -### 2. Transition Timing - -**Convention**: 150ms ease-in-out for all state transitions. - -**Scan for violations**: -- [ ] Transitions using durations other than 150ms (or `theme.transitions.duration.short`) -- [ ] Transitions using easing other than ease-in-out -- [ ] Transitions using bounce, elastic, or spring easing (remove — feels dated) -- [ ] Missing transitions on interactive state changes (hover, focus, active) -- [ ] Transitions on layout properties (`width`, `height`, `top`, `left`) instead of `transform`/`opacity` - -### 3. Focus-Visible Style - -**Convention**: `:focus-visible` with 2px outline, offset 2px, high contrast (3:1 minimum against adjacent colours). - -**Scan for violations**: -- [ ] `outline: none` without `:focus-visible` replacement -- [ ] Focus styles on `:focus` instead of `:focus-visible` (shows ring on click) -- [ ] Inconsistent outline width, colour, or offset across components -- [ ] Missing focus styles entirely on interactive elements -- [ ] Focus ring colour that does not meet 3:1 contrast - -### 4. Spacing Method - -**Convention**: `theme.spacing()` in styled components and `sx` props. `var(--fa-spacing-*)` in static contexts. - -**Scan for violations**: -- [ ] Raw pixel values for padding/margin/gap (e.g., `padding: '16px'`) -- [ ] Mixed methods in the same component (some `theme.spacing()`, some raw values) -- [ ] Inconsistent spacing scale usage across similar components (e.g., one card uses `spacing(2)` for padding, another uses `spacing(3)`) - -### 5. Component Structure - -**Convention**: Per `docs/conventions/component-conventions.md`. - -**Scan for violations**: -- [ ] Missing `displayName` on the component -- [ ] Missing barrel export (`index.ts` with `export { default }` and `export *`) -- [ ] Missing JSDoc on props interface (every prop needs a `/** description */`) -- [ ] Missing JSDoc on the component itself -- [ ] Props defined as `type` instead of `interface` (interfaces produce better autodocs) -- [ ] Missing `sx` prop forwarding (every component must accept consumer overrides) -- [ ] Interactive elements not using `React.forwardRef` - -### 6. Story Coverage - -**Convention**: Per story coverage checklist in `docs/conventions/component-conventions.md`. - -**Scan for violations**: -- [ ] Missing `tags: ['autodocs']` in story meta -- [ ] Missing Default story -- [ ] Missing AllVariants story (if component has variants) -- [ ] Missing Disabled story (if component can be disabled) -- [ ] Missing Loading story (if component has loading state) -- [ ] Incorrect `title` prefix (should match tier: `Atoms/`, `Molecules/`, `Organisms/`) - -### 7. Naming Consistency - -**Scan for violations**: -- [ ] Component folder not in PascalCase -- [ ] File names not matching component name -- [ ] Inconsistent prop naming across similar components (e.g., `isDisabled` vs `disabled`, `colour` vs `color`) -- [ ] CSS custom properties not prefixed with `--fa-` - -## Normalize Process - -1. **Scan**: Read every component file in the target tier(s) -2. **Tabulate**: Build a comparison table for each dimension showing what each component does -3. **Identify outliers**: Find components that deviate from the convention -4. **Fix**: Update outlier components to match the convention -5. **Verify**: Ensure TypeScript compiles and Storybook renders after fixes - -## Normalization Report - -Present findings in this format: - -### Scan Summary - -| Dimension | Components scanned | Violations found | Fixed | -|-----------|-------------------|-----------------|-------| -| Token access | ? | ? | ? | -| Transitions | ? | ? | ? | -| Focus styles | ? | ? | ? | -| Spacing | ? | ? | ? | -| Structure | ? | ? | ? | -| Stories | ? | ? | ? | -| Naming | ? | ? | ? | - -### Violations Fixed - -For each fix, note: -- **Component**: Which component was changed -- **Dimension**: Which consistency rule was violated -- **Before**: What it was doing -- **After**: What it does now - -### System-Level Observations - -Note any patterns that suggest a convention should be updated (e.g., if most components deviate from the convention, perhaps the convention is wrong). - -**NEVER**: -- Change a component's behaviour or API — normalize only changes implementation details -- Fix one component and leave similar components unfixed — normalize the whole tier -- Change conventions without flagging it — if you think a convention should change, note it as an observation, do not unilaterally change the rule diff --git a/.claude/skills/polish/SKILL.md b/.claude/skills/polish/SKILL.md deleted file mode 100644 index 4c037f7..0000000 --- a/.claude/skills/polish/SKILL.md +++ /dev/null @@ -1,146 +0,0 @@ ---- -name: polish -description: Final production readiness pass — visual alignment, spacing consistency, interaction states, copy, edge cases. Use before marking a component done. -user-invocable: true -argument-hint: "[component or area to polish]" ---- - -Perform a meticulous final pass on a component or area, fixing every detail that separates good work from great work. Unlike audit/critique which only assess, **polish finds AND fixes issues**. - -**Target:** $ARGUMENTS - -## Preparation - -1. Read `docs/design-system.md` for FA design conventions -2. Read `docs/memory/decisions-log.md` for design rationale and prior decisions -3. Read the target component/area source files and stories -4. Reference `docs/reference/impeccable/polish-skill.md` for the full checklist -5. Reference `docs/conventions/component-conventions.md` for structural rules - -**FA context**: Funeral Arranger serves families in grief or distress. The design must feel warm, trustworthy, and calm. Touch targets >= 44px. Transitions 150ms ease-in-out. No aggressive colours for errors (copper, not red — see D024). Accessibility is critical — users may be elderly, emotional, or on mobile. - -**CRITICAL**: Polish is the last step, not the first. Do not polish work that is not functionally complete. If the component has open TODOs or missing features, flag them and skip those areas. - -## Pre-Polish Assessment - -Before fixing anything, assess the current state: - -1. **Review completeness** — Is the component functionally complete? Are there known issues to preserve (mark with TODOs)? -2. **Identify polish areas** — Scan for visual inconsistencies, spacing issues, interaction state gaps, copy problems, edge cases, and transition roughness. -3. **Set scope** — List the specific fixes to make. Do not attempt structural changes — polish is micro-detail work. - -## Polish Systematically - -Work through each dimension. **Fix issues as you find them** — do not just document. - -### 1. Visual Alignment & Spacing - -- **Grid alignment**: All elements line up to the spacing scale (no arbitrary gaps) -- **Consistent spacing**: Every gap uses `theme.spacing()` or `var(--fa-spacing-*)` — no magic numbers -- **Optical alignment**: Adjust for visual weight where needed (icons often need offset for optical centering) -- **Responsive consistency**: Spacing works at all breakpoints (mobile, tablet, desktop) - -**How to check**: Inspect computed styles. Look for values that are not multiples of 4px or 8px. Squint at the layout — anything that feels off probably is. - -### 2. Typography Refinement - -- **Hierarchy consistency**: Same element types use the same typography variant throughout -- **Line length**: Body text stays within 45-75 characters -- **Line height**: Appropriate for font size and reading context -- **Token compliance**: All font sizes, weights, and families come from `theme.typography.*` - -### 3. Colour & Contrast - -- **Contrast ratios**: All text meets WCAG AA (4.5:1 for normal text, 3:1 for large text and UI) -- **Token usage**: No hardcoded hex values — all via theme palette or CSS variables -- **Tinted neutrals**: No pure gray or pure black — add subtle colour tint per FA palette -- **Gray on colour**: Never put gray text on coloured backgrounds — use a shade of that colour - -### 4. Interaction States - -Every interactive element must have ALL of these states: - -| State | Treatment | FA note | -|-------|-----------|---------| -| Default | Base styling | Warm, inviting | -| Hover | Subtle lift, colour shift | 150ms ease-in-out | -| Focus | Visible ring via `:focus-visible` | 2px, offset 2px, high contrast | -| Active | Pressed/darker | Immediate feedback | -| Disabled | Reduced opacity, `aria-disabled` | Clearly non-interactive | -| Loading | Spinner or skeleton | Reduce perceived wait | -| Error | Copper border/text, not red | Gentle, per D024 | -| Success | Confirmation feedback | Reassuring, not flashy | - -**The common miss**: Designing hover without focus. Keyboard users never see hover states. - -### 5. Micro-interactions & Transitions - -- **Timing**: All transitions 150ms ease-in-out (FA convention) -- **Properties**: Only animate `transform`, `opacity`, `background-color`, `border-color`, `box-shadow` — never animate `width`, `height`, or `top`/`left` -- **Reduced motion**: Must respect `prefers-reduced-motion` -- **Easing**: Ease-in-out or ease-out. Never bounce or elastic — they feel dated. - -### 6. Copy & Content - -- **Consistent terminology**: Same things called the same names throughout -- **Capitalisation**: Sentence case for body, consistent for labels -- **Tone**: Warm, professional, clear — no jargon, no condescension -- **Labels**: Unambiguous — a user should never wonder "what does this mean?" -- **Punctuation**: Consistent (periods on sentences, not on labels) - -### 7. Edge Cases - -- **Long content**: Handles very long names, descriptions, prices -- **Empty states**: Helpful guidance, not blank space -- **Missing data**: Graceful degradation with sensible defaults -- **Loading states**: Clear async feedback, skeleton over spinner where possible -- **Error states**: Helpful, non-blaming messages with recovery paths (copper, not red) - -### 8. Code Cleanliness - -- Remove `console.log` statements -- Remove commented-out code -- Remove unused imports -- Verify `displayName` is set on the component -- Verify barrel export in `index.ts` -- Ensure all props have JSDoc descriptions -- No TypeScript `any` types - -## Polish Checklist - -Verify each item after completing fixes: - -- [ ] Visual alignment correct at all breakpoints -- [ ] Spacing uses design tokens consistently (no magic numbers) -- [ ] Typography hierarchy consistent -- [ ] All interactive states implemented (hover, focus, active, disabled, loading, error) -- [ ] All transitions 150ms ease-in-out -- [ ] Focus indicators visible via `:focus-visible` -- [ ] Copy is consistent, warm, and unambiguous -- [ ] Touch targets >= 44px on all interactive elements -- [ ] Contrast ratios meet WCAG AA -- [ ] Keyboard navigation works correctly -- [ ] No console errors or warnings -- [ ] No layout shift on load -- [ ] Respects `prefers-reduced-motion` -- [ ] Code is clean (no TODOs, console.logs, commented code, unused imports) -- [ ] Component has `displayName` and barrel export -- [ ] All props have JSDoc descriptions - -## Final Verification - -After all fixes: - -1. **Check Storybook** — Verify all stories render correctly -2. **Check TypeScript** — Ensure no type errors introduced -3. **Compare states** — Walk through every interactive state visually -4. **Test keyboard** — Tab through the component, verify focus order and indicators - -**NEVER**: -- Polish before the component is functionally complete -- Introduce bugs while polishing (test thoroughly after each fix) -- Ignore systematic issues (if spacing is off everywhere, fix the system not individual instances) -- Perfect one area while leaving others rough (maintain consistent quality level) -- Make structural or architectural changes — that is not polish work - -Report a summary of what was fixed when done. diff --git a/.claude/skills/preflight/SKILL.md b/.claude/skills/preflight/SKILL.md deleted file mode 100644 index 95d2c5c..0000000 --- a/.claude/skills/preflight/SKILL.md +++ /dev/null @@ -1,111 +0,0 @@ ---- -name: preflight -description: Pre-commit quality check — verifies TypeScript, ESLint, Prettier, Storybook, token sync, and no hardcoded values -argument-hint: "[--fix to auto-fix issues]" ---- - -Run quality checks before committing. Reports pass/fail for each check and blocks commit if critical issues are found. - -**Mode:** $ARGUMENTS (pass `--fix` to attempt auto-fixes, otherwise report-only) - -**Run these checks in order:** - -### 1. TypeScript compilation -```bash -npx tsc --noEmit 2>&1 | grep -v "tokens.js" -``` -- **Pass:** No errors (the tokens.js declaration warning is a known pre-existing issue — ignore it) -- **Fail:** Any other TypeScript errors → report them -- **Critical:** Yes — do not commit if this fails - -### 2. Storybook build -```bash -npx storybook build --quiet 2>&1 -``` -- **Pass:** Build succeeds -- **Fail:** Build errors → report them -- **Critical:** Yes — do not commit if this fails - -### 3. Token sync check -Compare timestamps: do the generated outputs (`src/theme/generated/tokens.js`, `src/theme/generated/tokens.css`) have an older modification time than any `tokens/**/*.json` file? -```bash -# Find newest token JSON file -newest_token=$(find tokens/ -name "*.json" -newer src/theme/generated/tokens.js 2>/dev/null | head -5) -``` -- **Pass:** No token JSON files are newer than the generated outputs -- **Fail:** Token JSON was modified but outputs weren't regenerated -- **Fix:** Run `npm run build:tokens` -- **Critical:** Yes — stale generated tokens cause silent bugs - -### 4. Hardcoded values scan -Scan component files for hardcoded colours, spacing, and font values that should use tokens: -```bash -# Check for hex colours in component files (excluding stories and tokens) -grep -rn "#[0-9a-fA-F]\{3,8\}" src/components/ --include="*.tsx" --include="*.ts" | grep -v ".stories." | grep -v "// ok-hardcode" -``` -- **Pass:** No hex colours found in component source files (stories are exempt) -- **Fail:** Hardcoded values found → report file and line -- **Note:** Lines with `// ok-hardcode` comment are exempted (for rare intentional cases) -- **Critical:** No — warn but don't block commit - -### 5. Component exports check -Verify each component folder has a barrel export (`index.ts`) and the component has `displayName`: -```bash -# Check for missing index.ts -for dir in src/components/atoms/*/; do - [ -f "$dir/index.ts" ] || echo "Missing index.ts: $dir" -done -# Check for missing displayName (exclude stories) -find src/components/atoms/ -name "*.tsx" ! -name "*.stories.tsx" | xargs grep -L "displayName" 2>/dev/null -``` -- **Pass:** All component folders have index.ts and components set displayName -- **Fail:** Missing exports or displayName -- **Critical:** No — warn but don't block commit - -### 6. ESLint -```bash -npm run lint 2>&1 -``` -- **Pass:** No errors -- **Fail:** ESLint errors → report them -- **Fix:** Run `npm run lint:fix` -- **Critical:** Yes — do not commit if this fails - -### 7. Prettier -```bash -npm run format:check 2>&1 -``` -- **Pass:** All files formatted correctly -- **Fail:** Formatting issues found → report them -- **Fix:** Run `npm run format` -- **Critical:** No — warn but don't block commit (Husky pre-commit hook auto-fixes these) - -### Report format -``` -PREFLIGHT RESULTS -═══════════════════════════════ -✓ TypeScript .............. PASS -✓ Storybook build ........ PASS -✓ Token sync ............. PASS -⚠ Hardcoded values ....... WARN (2 issues) -✓ Component exports ...... PASS -✓ ESLint ................. PASS -✓ Prettier ............... PASS -─────────────────────────────── -Result: PASS (safe to commit) -``` - -Use `PASS`, `FAIL`, or `WARN`. If any critical check fails, the result is `FAIL (do not commit)`. If only warnings, result is `PASS (safe to commit)` with warnings listed. - -If `--fix` was passed, attempt to fix issues automatically (e.g., run `npm run build:tokens` for stale tokens) and re-check. - -### 8. Visual QA spot-check (manual review, non-blocking) - -If a component was recently modified, do a quick visual review of the source code for these common issues (adapted from impeccable /polish): - -- **Transition consistency**: All interactive state changes should use `150ms ease-in-out` (FA convention). Flag mismatches. -- **Focus-visible**: Every interactive element should have a `:focus-visible` style. Flag any that rely only on hover. -- **Touch targets**: Interactive elements should have `minHeight >= 44px` for the largest size (or the mobile-intended size). -- **Spacing consistency**: Padding/gap values should use `theme.spacing()` or token CSS variables, not raw px. - -These are advisory — report as `INFO` lines after the main results. Do not block commit for these. diff --git a/.claude/skills/publish/SKILL.md b/.claude/skills/publish/SKILL.md deleted file mode 100644 index 05b1eb9..0000000 --- a/.claude/skills/publish/SKILL.md +++ /dev/null @@ -1,93 +0,0 @@ -Publish the project to all three targets: backup, dev remotes, and Chromatic. - -## Workflow - -### Step 1 — Pre-flight check - -1. Ensure there are no uncommitted changes: `git status --porcelain` - - If dirty, ask the user if they want to commit first -2. Run `npx tsc --noEmit` to verify the build is clean - - If it fails, stop and report errors - -### Step 2 — Push to backup (everything) - -Push main directly to the `backup` remote (git.tensordesign.com.au/richie/ParsonsFA). This is a private repo that receives the full repo including AI tooling, memory, and working docs. - -```bash -git push backup main -``` - -If rejected (non-fast-forward), warn the user and ask before force-pushing. - -### Step 3 — Push to dev remotes (stripped) - -Both `fa-dev` and `sheffield` receive a stripped version with AI tooling removed. Use a temporary worktree to avoid touching the working directory. - -```bash -# Clean up any prior worktree -git worktree remove --force /tmp/dev-push 2>/dev/null -git branch -D dev-clean 2>/dev/null - -# Create worktree from current main -git worktree add /tmp/dev-push -b dev-clean - -# In the worktree, remove AI tooling from the index -cd /tmp/dev-push -for path in .claude/ docs/memory/ docs/reference/; do - git rm -r --cached "$path" 2>/dev/null -done -git commit -m "Strip AI tooling and working docs for dev push" - -# Push stripped branch to both dev remotes -cd -git push fa-dev dev-clean:main --force -git push sheffield dev-clean:main --force - -# Clean up -git worktree remove --force /tmp/dev-push -git branch -D dev-clean -``` - -**Important:** The `--force` is safe here because the stripped branch is always regenerated from main. Dev remotes never have unique commits. - -### Step 4 — Sync assets to Gitea - -Push the `brandassets/` directory to the dedicated assets repo so Chromatic can load images via external URLs. - -```bash -cd /tmp -rm -rf ParsonsAssets -git clone https://richie:151fdccacf11b6190d066a7e07f6f5310b2227dd@git.tensordesign.com.au/richie/ParsonsAssets.git -rsync -a --delete /brandassets/ /tmp/ParsonsAssets/ --exclude='.git' -cd /tmp/ParsonsAssets -git add -A -git diff --cached --quiet || git commit -m "Sync assets from main project" -git push origin main -cd -rm -rf /tmp/ParsonsAssets -``` - -This step is idempotent — if nothing changed, no commit is created. Skip if you know no images were added or changed since last publish. - -### Step 5 — Deploy to Chromatic - -```bash -STORYBOOK_ASSET_BASE=https://git.tensordesign.com.au/richie/ParsonsAssets/raw/branch/main npm run chromatic -``` - -The `STORYBOOK_ASSET_BASE` env var tells `assetUrl()` to resolve image paths from the Gitea assets repo instead of local static files. Run this in the background. Report the Storybook URL and build link when complete. - -### Step 6 — Report - -Summarise what was pushed: - -``` -Published to all targets: -- backup → git.tensordesign.com.au/richie/ParsonsFA (full) -- fa-dev → git.tensordesign.com.au/richie/Parsons (stripped) -- sheffield → sheffield.sapiente.casa/richie/ParsonsFA (stripped) -- assets → git.tensordesign.com.au/richie/ParsonsAssets (synced) -- Chromatic → [build link] -``` - -If any target failed, report which ones succeeded and which failed. diff --git a/.claude/skills/quieter/SKILL.md b/.claude/skills/quieter/SKILL.md deleted file mode 100644 index d165584..0000000 --- a/.claude/skills/quieter/SKILL.md +++ /dev/null @@ -1,131 +0,0 @@ ---- -name: quieter -description: Calmer design pass — reduces visual noise, aggressive colours, competing weights, and transactional copy. Highly FA-specific for grief-sensitive context. -user-invocable: true -argument-hint: "[component or area to quiet]" ---- - -Run a grief-sensitive design pass on a component or area, then **fix issues found**. This is assessment AND fix — diagnose anything that feels too loud, too urgent, or too transactional for a funeral planning context, then apply corrections. - -**Target:** $ARGUMENTS - -## Preparation - -1. Read `docs/design-system.md` for FA brand guidelines and tone -2. Read `docs/memory/decisions-log.md` for colour and tone decisions (especially D024 for error treatment) -3. Read the target component/area source files and stories -4. Reference `docs/reference/impeccable/color-and-contrast.md` for colour usage principles -5. Reference `docs/reference/impeccable/personas.md` for user archetypes (especially Jordan — confused first-timer, and Casey — distracted mobile user) - -**FA context reminder**: "Understated empathy — warm but not gushy. Let UI structure be the empathy." Users are often elderly, emotional, and unfamiliar with technology. They may be planning a funeral for a loved one who has just died. Design must feel like a trusted advisor, not a sales platform. Every element that demands attention should earn it. Silence and space are design tools. - -## Diagnostic Checks - -Work through each check systematically. For each issue found, note the problem, then fix it. - -### 1. Aggressive Colour Treatment - -- **Error states must NOT use aggressive red** — FA uses a softer copper/warm treatment for errors (per D024) -- Check for bright, saturated reds (#ff0000, #e53935, MUI error.main defaults) in error messages, validation, or alerts -- Replace with the FA copper error palette from the theme (`palette.error.main` should already be the soft treatment) -- Warning states should also be warm, not harsh yellow/orange -- Success states should be muted green, not vivid/celebratory -- Check that semantic colours come from the theme, not hardcoded aggressive values - -### 2. High Saturation Where Muted Would Be Better - -- Scan for highly saturated colours that draw disproportionate attention -- Background colours should be muted — surfaces use the warm neutral palette, not bright fills -- Accent colours work because they are rare (60-30-10 rule) — if accent is used liberally, it stops working -- Icons and decorative elements should use muted tones unless they serve a functional purpose -- Check that the warm gold/copper brand palette is cohesive — no jarring colour outliers - -### 3. Competing Visual Weights - -- Look for multiple bold or heavy elements fighting for attention in the same view -- There should be one clear primary focal point — if multiple elements scream for attention, quiet the secondary ones -- Bold text should be used for emphasis, not as default — if everything is bold, nothing is -- Check for multiple large/heavy headings at the same level competing with each other -- Reduce weight on supporting elements (metadata, labels, secondary info) to let primary content breathe - -### 4. Insufficient Whitespace - -- Check padding and margins — grief-sensitive design needs generous breathing room -- Cards, sections, and content blocks should have ample internal padding -- Vertical spacing between sections should feel restful, not cramped -- Dense layouts feel overwhelming for users in emotional distress — space creates calm -- Check that spacing values come from the theme spacing scale, and lean toward the generous end - -### 5. Urgent Animations and Transitions - -- Animations should feel gentle, not snappy or urgent -- Check for bounce/elastic easing — replace with ease-out or ease-in-out -- Transition durations should be moderate (200-400ms for UI, longer for content reveals) -- No attention-grabbing animations (pulse, shake, flash) — these feel demanding -- Loading states should feel patient, not frantic -- If an animation can be removed without losing meaning, consider removing it - -### 6. Transactional Copy - -- Copy should feel empathetic and guiding, not sales-driven or transactional -- Check button labels: "Buy Now", "Add to Cart", "Submit" feel transactional — prefer "Continue", "Next Step", "Confirm Details" -- Check headings: avoid language that feels like a sales funnel ("Choose Your Package", "Upgrade", "Best Value") -- Error messages should be gentle and helpful, never blaming ("Something went wrong" not "You entered an invalid...") -- Avoid urgency language ("Limited time", "Act now", "Don't miss out") — this is deeply inappropriate in a grief context -- Pricing should be presented transparently, not with sales psychology (no crossed-out prices, no "savings" badges) -- Check for placeholder/lorem text that may have a casual or inappropriate tone - -### 7. CTA Hierarchy - -- There should be ONE clear primary CTA per view/section — not multiple competing calls to action -- Secondary actions should be visually distinct (outlined, text-only) not just smaller versions of primary buttons -- If there are more than 2 CTAs visible simultaneously, evaluate whether some can be demoted or removed -- The primary CTA should feel inviting, not pressuring — warm brand colour, not aggressive contrast -- Check that button hierarchy uses theme variants correctly (contained for primary, outlined for secondary, text for tertiary) - -## Fix Process - -For each issue found: - -1. **Identify** the file, line, and current value -2. **Assess emotional impact** — how does this element feel to a grieving user? -3. **Determine the quieter alternative** — what change reduces noise while preserving function? -4. **Apply the fix** — update colours, weights, spacing, copy, or animation values -5. **Verify** the fix doesn't make the element invisible or non-functional — quiet does not mean hidden - -## Report Format - -After fixing, present a summary: - -### Quiet Pass Summary - -| Check | Status | Issues Found | Issues Fixed | -|-------|--------|-------------|-------------| -| Aggressive Colours | pass/warn/fail | N | N | -| High Saturation | pass/warn/fail | N | N | -| Competing Weights | pass/warn/fail | N | N | -| Whitespace | pass/warn/fail | N | N | -| Animations/Transitions | pass/warn/fail | N | N | -| Transactional Copy | pass/warn/fail | N | N | -| CTA Hierarchy | pass/warn/fail | N | N | - -### Emotional Tone Assessment - -Brief statement on the overall emotional register of the component: -- Does it feel like a **trusted advisor** or a **sales platform**? -- Would a grieving family member feel **supported** or **pressured**? -- Is the design **calm** or **demanding**? - -### Changes Made - -For each fix applied: -- **What changed**: Brief description -- **File**: Path and relevant line(s) -- **Before/After**: The old and new values -- **Why**: How this change serves the grief-sensitive context - -### Remaining Concerns - -Any issues that need design input, copy review, or are outside the scope of a quieting pass. - -**NEVER**: Use aggressive red for error states. Add urgency language or sales psychology. Make everything equally loud. Remove functional affordances in the name of minimalism. Ignore that real people in real pain will use this interface. diff --git a/.claude/skills/review-component/SKILL.md b/.claude/skills/review-component/SKILL.md deleted file mode 100644 index 014e014..0000000 --- a/.claude/skills/review-component/SKILL.md +++ /dev/null @@ -1,68 +0,0 @@ ---- -name: review-component -description: Review a component against design system conventions -argument-hint: "[ComponentName]" ---- - -Review a component against FA Design System conventions and report pass/fail for each check. - -**Component to review:** $ARGUMENTS - -**Instructions:** -1. Read `docs/conventions/component-conventions.md` for the rules -2. Read `docs/conventions/token-conventions.md` for token usage rules -3. Read the component source file in `src/components/` -4. Read the component's Storybook stories -5. Reference `docs/reference/vercel/react-best-practices.md` for React performance patterns (optional, for deeper code quality review) - -**Check each of these and report pass/fail:** - -### Code quality -- [ ] Component uses TypeScript with proper types -- [ ] Props interface exported with JSDoc on every prop -- [ ] Uses `React.forwardRef` for interactive elements -- [ ] Accepts and forwards `sx` prop -- [ ] Uses `shouldForwardProp` for custom props on styled components - -### Theme compliance -- [ ] NO hardcoded colours — all from `theme.palette.*` -- [ ] NO hardcoded spacing — all from `theme.spacing()` -- [ ] NO hardcoded typography — all from `theme.typography.*` -- [ ] NO hardcoded shadows — all from `theme.shadows` -- [ ] NO hardcoded border radius — all from `theme.shape.*` - -### Accessibility -- [ ] Minimum 44px touch target on mobile -- [ ] Visible focus indicator (focus-visible) -- [ ] Appropriate ARIA attributes -- [ ] Disabled state uses `aria-disabled` -- [ ] Colour contrast meets WCAG 2.1 AA - -### Storybook coverage -- [ ] Default story -- [ ] All variants story -- [ ] All sizes story (if applicable) -- [ ] Disabled state -- [ ] Loading state (if applicable) -- [ ] Long content / overflow -- [ ] autodocs tag present - -### Interactive states (ref: docs/reference/impeccable/interaction-design.md) -- [ ] Default (resting) state is styled -- [ ] Hover state provides visual feedback (not just cursor change) -- [ ] Focus-visible state is distinct from hover (keyboard users never see hover) -- [ ] Active/pressed state feels responsive -- [ ] Disabled state is visually diminished but still distinguishable -- [ ] Transitions use 150ms ease-in-out (FA convention) - -### Design anti-patterns (ref: docs/reference/impeccable/frontend-design-skill.md) -- [ ] No grey text on coloured backgrounds (use a shade of the background colour instead) -- [ ] No cards nested inside cards (flatten hierarchy with spacing/typography) -- [ ] No identical card grids with zero variation (vary content, size, or emphasis) -- [ ] No bounce/elastic easing (use ease-out-quart or ease-in-out) -- [ ] Not every button is primary (use variant hierarchy: contained > soft > outlined > text) -- [ ] No redundant copy (headings don't restate content below them) -- [ ] No glassmorphism/blur used purely as decoration -- [ ] Whitespace is intentional, not leftover - -**Report format:** List each check with pass/fail and specific issues found. End with a summary and recommended fixes. diff --git a/.claude/skills/status/SKILL.md b/.claude/skills/status/SKILL.md deleted file mode 100644 index 4c59324..0000000 --- a/.claude/skills/status/SKILL.md +++ /dev/null @@ -1,35 +0,0 @@ ---- -name: status -description: Report current status of tokens, components, and build health ---- - -Report the current status of the FA Design System. - -**Instructions:** -1. Read `docs/memory/session-log.md` — summarise recent work -2. Read `docs/memory/component-registry.md` — count components by status (planned, in-progress, review, done) -3. Read `docs/memory/token-registry.md` — summarise token coverage -4. Read `docs/memory/decisions-log.md` — count decisions logged -5. Check if Storybook is running (curl http://localhost:6006) -6. Check if tokens build successfully (`npm run build:tokens`) - -**Report format:** -``` -## FA Design System Status - -### Tokens -- Primitives: [count] defined -- Semantic: [count] defined -- Component: [count] defined - -### Components -- Done: [list] -- In progress: [list] -- Planned: [list] - -### Recent activity -- [last session summary] - -### Next steps -- [recommended next actions] -``` diff --git a/.claude/skills/sync-tokens/SKILL.md b/.claude/skills/sync-tokens/SKILL.md deleted file mode 100644 index 1852937..0000000 --- a/.claude/skills/sync-tokens/SKILL.md +++ /dev/null @@ -1,22 +0,0 @@ ---- -name: sync-tokens -description: Rebuild CSS and JS outputs from token JSON sources ---- - -Synchronise design tokens — rebuild CSS and JS outputs from token JSON sources. - -Use this after token JSON files have been edited manually or after `/create-tokens`. This is a maintenance command — it does NOT create new tokens (use `/create-tokens` for that). - -Use the token-architect agent to handle this task. - -**Instructions for the agent:** -1. Read `docs/memory/token-registry.md` to understand current token state -2. Validate all token JSON files have required fields (`$value`, `$type`, `$description`) -3. Run `npm run build:tokens` to regenerate: - - `src/theme/generated/tokens.css` (CSS custom properties) - - `src/theme/generated/tokens.js` (JS ES6 module) - - `tokens/export/tokens-flat.json` (flat JSON export) -4. Check that `src/theme/index.ts` is consuming the generated tokens correctly -5. If any tokens were added/changed since the theme was last updated, update `src/theme/index.ts` -6. Report what was generated and any issues found -7. Update `docs/memory/token-registry.md` if it's out of date diff --git a/.claude/skills/typeset/SKILL.md b/.claude/skills/typeset/SKILL.md deleted file mode 100644 index e303997..0000000 --- a/.claude/skills/typeset/SKILL.md +++ /dev/null @@ -1,116 +0,0 @@ ---- -name: typeset -description: Typography refinement — checks hierarchy consistency, line length, line height, font weight, and mobile readability across a component or area. -user-invocable: true -argument-hint: "[component or area to typeset]" ---- - -Run a typography-focused review on a component or area, then **fix issues found**. This is assessment AND fix — diagnose problems, then apply corrections. - -**Target:** $ARGUMENTS - -## Preparation - -1. Read `docs/design-system.md` for FA typography conventions -2. Read `docs/memory/token-registry.md` for the current type scale and weight decisions -3. Read `docs/memory/decisions-log.md` for typography-related decisions (especially D017, D019) -4. Read the target component/area source files and stories -5. Reference `docs/reference/impeccable/typography.md` for detailed typographic guidelines - -**FA context reminder**: Funeral Arranger serves families often in grief or distress. Many users are elderly, on mobile, and reading under emotional strain. Typography must prioritise readability and calm hierarchy over visual flair. Warmth comes through the serif display type (Noto Serif SC) at display sizes — not through decorative overuse. Body text must be effortlessly readable. - -## Diagnostic Checks - -Work through each check systematically. For each issue found, note the problem, then fix it. - -### 1. Hierarchy Consistency - -- Same semantic level must have the same visual treatment everywhere in the target -- Heading levels should use the correct MUI typography variant (h1-h6, subtitle1/2, body1/2) -- No more than 3-4 distinct text sizes visible at once (muddy hierarchy = too many similar sizes) -- Size jumps between levels should be clear — avoid sizes too close together (e.g., 14px, 15px, 16px) -- Check that the modular scale from the token system is followed consistently - -### 2. Line Length (Measure) - -- Body text should be constrained to 45-75 characters per line (`max-width: 65ch` is a good default) -- If body text runs full-width on desktop, add a `max-width` using `ch` units -- Narrow columns (sidebars, cards) may go below 45ch — tighten line-height to compensate -- Wide text blocks strain reading comprehension, especially for elderly/distressed users - -### 3. Line Height - -- Body text: 1.5-1.6 line-height for comfortable reading -- Headings: tighter line-height (1.1-1.3) since larger text needs less relative leading -- Line-height scales inversely with line length — narrow columns need tighter leading, wide columns need more -- Light text on dark backgrounds needs ~0.05-0.1 more line-height than normal -- Vertical rhythm: spacing values should relate to the base line-height unit - -### 4. Font Weight Consistency - -- **Body weight must be Medium 500** (per D019) — check that body text is not using 400 (Regular) -- Headings should use consistent weights within tiers (all h2s same weight, all h3s same weight) -- Avoid more than 3 font weights in the same view — too many competing weights create noise -- Bold should be used for emphasis, not as a default state for UI elements -- Check that weight values come from the theme, not hardcoded - -### 5. Display Font Usage - -- **Noto Serif SC is for display variants only** (per D017) — hero text, display headings, featured quotes -- Noto Serif SC must NOT be used for standard headings (h1-h6 in regular UI contexts) -- Standard headings use the sans-serif stack (Figtree or system font) -- If the serif font appears on a regular heading, replace it with the sans-serif variant - -### 6. Mobile Font Size Adequacy - -- Body text minimum 14px on mobile (16px preferred, per impeccable guidelines) -- Small/caption text minimum 12px -- Touch-target text (buttons, links in body) must be large enough to tap accurately -- Check that `rem` units are used (not `px`) so text respects browser zoom settings -- Verify no `user-scalable=no` in viewport meta (breaks accessibility) - -### 7. Token Compliance - -- All font sizes should come from theme.typography variants, not hardcoded values -- All font weights should come from theme tokens -- All line-heights should come from theme tokens -- Font family should come from theme, never hardcoded strings -- Check for inline `style` props that override typography tokens - -## Fix Process - -For each issue found: - -1. **Identify** the file, line, and current value -2. **Reference** the correct token/theme value it should use -3. **Apply the fix** — update the component source to use the correct theme value -4. **Verify** the fix maintains visual intent (don't blindly replace — ensure the result looks right) - -## Report Format - -After fixing, present a summary: - -### Typography Health Summary - -| Check | Status | Issues Found | Issues Fixed | -|-------|--------|-------------|-------------| -| Hierarchy Consistency | pass/warn/fail | N | N | -| Line Length | pass/warn/fail | N | N | -| Line Height | pass/warn/fail | N | N | -| Font Weight | pass/warn/fail | N | N | -| Display Font Usage | pass/warn/fail | N | N | -| Mobile Font Size | pass/warn/fail | N | N | -| Token Compliance | pass/warn/fail | N | N | - -### Changes Made - -For each fix applied: -- **What changed**: Brief description -- **File**: Path and relevant line(s) -- **Before/After**: The old and new values - -### Remaining Concerns - -Any issues that need design input or are outside the scope of a typesetting pass. - -**NEVER**: Hardcode font sizes in px. Use the serif display font (Noto Serif SC) for regular headings. Set body weight to 400 (Regular) — FA uses 500 (Medium). Remove typography tokens in favour of inline styles. Ignore mobile readability. diff --git a/.claude/skills/write-stories/SKILL.md b/.claude/skills/write-stories/SKILL.md deleted file mode 100644 index 1b66f63..0000000 --- a/.claude/skills/write-stories/SKILL.md +++ /dev/null @@ -1,29 +0,0 @@ ---- -name: write-stories -description: Write or update Storybook stories for a component -argument-hint: "[ComponentName]" ---- - -Write or update Storybook stories for an existing component. - -Use the story-writer agent to handle this task. The component to document: - -**Component:** $ARGUMENTS - -**Instructions for the agent:** -1. Read `docs/conventions/component-conventions.md` for story standards -2. Read the component source file at `src/components/` (check atoms/, molecules/, organisms/) -3. Create or update `{ComponentName}.stories.tsx` in the component's folder -4. Cover ALL items in the story coverage checklist: - - [ ] Default state with typical content - - [ ] All visual variants side by side - - [ ] All sizes side by side (if applicable) - - [ ] Disabled state - - [ ] Loading state (if applicable) - - [ ] Error state (if applicable) - - [ ] Long content / content overflow - - [ ] Empty/minimal content - - [ ] With and without optional elements (icons, badges, etc.) -5. Every story meta MUST include `tags: ['autodocs']` -6. Verify the component renders correctly in Storybook at http://localhost:6006 -7. Update `docs/memory/session-log.md` when done diff --git a/.claude/skills/write-tests/SKILL.md b/.claude/skills/write-tests/SKILL.md deleted file mode 100644 index 99bc370..0000000 --- a/.claude/skills/write-tests/SKILL.md +++ /dev/null @@ -1,101 +0,0 @@ ---- -name: write-tests -description: Write or update tests for a component — determines whether it needs unit tests (Vitest), interaction tests (Storybook play), or both, then generates appropriate test code. -user-invocable: true -argument-hint: "[ComponentName]" ---- - -Write tests for the specified component. - -**Component:** $ARGUMENTS - -## Preparation - -1. Read `docs/conventions/component-conventions.md` for component patterns -2. Read the component source file in `src/components/` -3. Read the component's existing Storybook stories -4. Check `docs/memory/component-registry.md` for component status and composition - -## Determine Test Strategy - -Categorise the component: - -### Interactive components (need Storybook `play` functions) -Components with user interactions: clicks, toggles, keyboard navigation, form inputs, selection state changes. - -**Examples:** Button, Input, SearchBar, ServiceOption, AddOnOption, Switch, Radio, FuneralFinder - -For these, add `play` functions to existing stories: -```tsx -import { expect, userEvent, within } from '@storybook/test'; - -export const ClickTest: Story = { - play: async ({ canvasElement }) => { - const canvas = within(canvasElement); - const button = canvas.getByRole('button'); - await userEvent.click(button); - await expect(button).toBeVisible(); - }, -}; -``` - -**What to test in `play` functions:** -- Click/tap fires expected callback -- Disabled state prevents interaction -- Keyboard navigation works (Enter, Space, Arrow keys) -- Loading state disables interaction -- Error states show correct feedback -- Selection state changes visually -- Form validation triggers on submit - -### Logic-heavy components (need Vitest unit tests) -Components with significant internal logic: conditional rendering, validation, state machines, computed values. - -**Examples:** FuneralFinder (validation logic), PackageDetail (price calculations), ServiceSelector (selection management) - -Create `{ComponentName}.test.tsx` alongside the component: -```tsx -import { describe, it, expect } from 'vitest'; -import { render, screen } from '@testing-library/react'; -import userEvent from '@testing-library/user-event'; -import { ThemeProvider } from '@mui/material/styles'; -import theme from '../../../theme'; -import { ComponentName } from './ComponentName'; - -const renderWithTheme = (ui: React.ReactElement) => - render({ui}); - -describe('ComponentName', () => { - it('renders with default props', () => { - renderWithTheme(); - expect(screen.getByRole('...')).toBeInTheDocument(); - }); -}); -``` - -**What to test in Vitest:** -- Conditional rendering logic (shows/hides elements based on props) -- Validation rules (required fields, format checks) -- Callback props fire with correct arguments -- Accessibility: correct ARIA roles and states -- Edge cases: empty data, maximum values, missing optional props - -### Display-only components (minimal testing needed) -Components that only render static content from props: Typography, Badge, Divider, Card (non-interactive). - -For these, stories ARE the tests. Ensure stories cover all variants. No additional test files needed unless there's conditional rendering logic. - -## After Writing Tests - -1. Run `npm run test` to verify Vitest tests pass -2. If Storybook `play` functions were added, verify they work in Storybook's test panel -3. Update `docs/memory/component-registry.md` with test status note - -## Rules - -- Always wrap components in `ThemeProvider` with FA theme in Vitest tests -- Use `screen.getByRole()` over `getByTestId()` — test what the user sees -- Test behaviour, not implementation — don't test internal state directly -- Keep tests focused: one assertion per test where practical -- Don't test MUI internals — only test our component's API -- Don't snapshot test — snapshots are too brittle for an evolving design system diff --git a/docs/memory/component-registry.md b/docs/memory/component-registry.md deleted file mode 100644 index f2799ce..0000000 --- a/docs/memory/component-registry.md +++ /dev/null @@ -1,122 +0,0 @@ -# Component registry - -Tracks the status, specification, and key details of every component in the -design system. Agents MUST check this before building a component (to avoid -duplicates) and MUST update it after completing one. - -## Status definitions - -- **planned**: Component is identified but not yet started -- **in-progress**: Component is being built -- **review**: Component is built, awaiting human review -- **done**: Component is reviewed and approved -- **needs-revision**: Component needs changes based on review feedback - -## Atoms - -| Component | Status | Variants | Tokens used | Notes | -|-----------|--------|----------|-------------|-------| -| Button | done | contained, soft, outlined, text × xs, small, medium, large × primary, secondary + loading, underline, fullWidth | button.height/paddingX/paddingY/fontSize/iconSize/iconGap/borderRadius, color.interactive.*, color.brand.100-300, color.neutral.200-700 | Primary interactive element. Merges Text Button from Figma. Soft variant = Figma's Secondary/Brand & Secondary/Grey. | -| IconButton | done | default, primary, secondary, error × small, medium, large | Reuses button.height/iconSize tokens, color.interactive.*, color.neutral.* | Icon-only button (close, menu, actions). Wraps MUI IconButton. Rounded rect, brand hover, focus ring. | -| Typography | done | displayHero, display1-3, displaySm, h1-h6, bodyLg, body1, body2, bodyXs, labelLg, label, labelSm, caption, captionSm, overline, overlineSm + maxLines, gutterBottom | typography.* (all semantic typography tokens), fontFamily.body, fontFamily.display | Text display system. Thin MUI wrapper with maxLines truncation. | -| Input | done | medium, small × default, hover, focus, error, success, disabled + startIcon, endIcon, required, multiline | input.height/paddingX/paddingY/fontSize/borderRadius/gap/iconSize, color.neutral.300-400, color.brand.500, color.feedback.error/success, color.text.secondary | External label pattern, branded focus ring, two sizes aligned with Button. Adds startIcon/endIcon and success state beyond Figma. | -| Badge | done | soft, filled × default, brand, success, warning, error, info × small, medium + icon | badge.height/paddingX/fontSize/iconSize/iconGap/borderRadius, color.feedback.*, color.brand.200/700 | Status indicator pill. Soft (tonal) or filled (solid). 6 colours, 2 sizes, optional leading icon. | -| Icon | planned | various sizes | | Icon wrapper component | -| Avatar | planned | image, initials, icon × small, medium, large | | User/entity representation | -| Divider | done | horizontal, vertical × fullWidth, inset, middle + text, flexItem | color.border.default (via palette.divider) | Visual separator. Wraps MUI Divider. Supports text children and orientation. | -| Chip | done | filled, outlined × small, medium × clickable, deletable, selected × default, primary | chip.height/paddingX/fontSize/iconSize/deleteIconSize/iconGap/borderRadius, color.neutral.200-700, color.brand.200-700 | Interactive tag. Wraps MUI Chip with FA tokens. Selected state promotes to brand colour. Filled uses soft tonal bg (like Badge). | -| Card | done | elevated, outlined × default, compact, none padding × interactive × selected | card.borderRadius/padding/shadow/border/background, color.surface.raised/subtle/warm, color.border.default/brand, shadow.md/lg | Content container. Elevated (shadow) or outlined (border). Interactive adds hover bg fill + shadow lift. Selected adds brand border + warm bg. Three padding presets. | -| Switch | done | bordered style × checked, unchecked, disabled | switch.track.width/height/borderRadius, switch.thumb.size, color.interactive.*, color.neutral.400 | Toggle for add-ons/options. Wraps MUI Switch. Bordered pill, brand.500 fill when active. From Parsons 1.0 Figma Style One. | -| Radio | done | checked, unchecked, disabled | radio.size/dotSize, color.interactive.*, color.neutral.400 | Single-select option. Wraps MUI Radio. Brand.500 fill when selected. From Parsons 1.0 Figma. | -| MapPin | done | name+price (two-line), name-only, price-only × verified, unverified × default, active | mapPin.paddingX/borderRadius/nub.size, color.brand.100-900, color.neutral.100-800 | Two-line label map marker: name (bold, truncated 180px) + "From $X" (centred, semibold). Name optional for price-only variant. Verified = brand palette, unverified = grey. Active inverts + scale. Pure CSS. role="button" + keyboard + focus ring. | -| ColourToggle | planned | inactive, hover, active, locked × single, two-colour × desktop, mobile | | Circular colour swatch picker for products. Custom component. Deferred until product detail organisms. | -| Slider | planned | single, range × desktop, mobile | | Price range filter. Wraps MUI Slider. Deferred until search/filtering molecules. | -| Link | done | underline: hover/always/none × any MUI colour | color.text.brand (copper brand.600, 4.8:1), color.interactive.active | Navigation text link. Wraps MUI Link. Copper default, underline on hover, focus ring. | -| Collapse | done | in/out × unmountOnExit | (none — uses MUI defaults) | Progressive disclosure wrapper. Thin MUI Collapse wrapper with unmountOnExit default. Slide-down animation for wizard field reveal. | -| DialogShell | done | open/closed × with/without back button × with/without footer | (theme defaults — borderRadius, palette) | Standard dialog container. Header (title + optional back + close), divider, scrollable body, optional footer. Used by FilterPanel and ArrangementDialog. | -| ToggleButtonGroup | done | exclusive single-select × small, medium, large × error × fullWidth + descriptions | color.neutral.100-200, color.brand.50/100, color.interactive.focus, color.feedback.error | Button-select for binary/small-set choices. Fieldset/legend a11y, external label, helper/error text. Brand styling on selected. | - -## Molecules - -| Component | Status | Composed of | Notes | -|-----------|--------|-------------|-------| -| MiniCard | done | Card + Typography + Badge + Tooltip | Compact vertical card for grids, recommendations, map popups. Image + title + optional price/badges/chips/meta (location, rating, capacity). Verified = icon-only circle badge in image. Hierarchy: title → meta → price → badges → chips. Truncated title shows tooltip. 3 component tokens. Audit: 20/20. | -| MapPopup | done | Paper + Typography + Tooltip | Floating map popup anchored to MapPin. Clickable card (onClick). Image + name (1 line, tooltip) + meta + price. Verified = icon-only circle badge in image (matches MiniCard). Hierarchy matches MiniCard. Nub + drop-shadow. 260px wide. | -| FormField | planned | Input + Typography (label) + Typography (helper) | Standard form field with label and validation | -| ProviderCard | done | Card + Typography + Badge + Tooltip | Provider listing card. Verified: image + logo (64px rounded rect) + "Verified" badge. Unverified: text-only with top accent bar. Capability badges with info icon + tooltip. Price split typography. No footer. 4 component tokens. | -| VenueCard | done | Card + Typography | Venue listing card. Always has photo + location + capacity ("X guests") + price ("From $X"). No verification tiers, no logo, no badges. 3 component tokens. Critique: 33/40. | -| MapCard | planned | Card + Typography + Badge | Compact horizontal map popup card. Deferred until map integration. | -| ServiceOption | done | Card (interactive, selected) + Typography | Selectable service option for arrangement flow. Heading + optional price (right-aligned) + optional description. role="radio" + aria-checked. Disabled state with opacity token. Maps to Figma ListItemPurchaseOption. | -| SearchBar | done | Input + IconButton + Button | Search input with optional submit button. Enter-to-submit, progressive clear button, inline loading spinner. Guards empty submissions, refocuses after clear. role="search" landmark. Critique: 35/40. | -| AddOnOption | done | Card (interactive, selected) + Typography + Switch | Toggleable add-on for arrangement flow extras. Heading + optional price + description + Switch. Click-anywhere toggle. Maps to Figma ListItemAddItem (2350:40658). | -| StepIndicator | done | Typography + Box | Horizontal segmented progress bar. Brand gold for completed/current steps, grey for upcoming. Responsive bar height (10px/6px). Maps to Figma Progress Bar - Steps (2375:47468). | -| LineItem | done | Typography + Tooltip + InfoOutlinedIcon | Name + optional info tooltip + optional price. Supports allowance asterisk, total variant (bold + top border). Font weight 500 (D019), prices text.secondary for readability hierarchy. Audit: 19/20. | -| ProviderCardCompact | done | Card (outlined) + Typography | Horizontal compact provider card — image left, name + location + rating right. Used at top of Package Select page. Separate from vertical ProviderCard. | -| CartButton | done | Button + DialogShell + LineItem + Divider + Typography | Outlined pill trigger: receipt icon + "Your Plan" + formatted total in brand colour. Click opens DialogShell with items grouped by section via LineItem, total row. Mobile: icon + price only. Lives in WizardLayout `runningTotal` slot. | -| CompareBar | done | Badge + Button + IconButton + Typography + Paper + Slide | Floating comparison basket pill. Fixed bottom, slide-up/down. Package count badge + provider names + remove buttons + Compare CTA. Max 3 user packages. Disabled CTA when <2. Inline error for max-reached. Mobile: compact count + CTA only. Audit: 18/20. | -| ComparisonPackageCard | done | Card + Badge + Button + Divider + Typography + Tooltip + LocationOnOutlinedIcon + VerifiedOutlinedIcon + CheckCircleOutlineIcon + InfoOutlinedIcon | Mobile full-width package card for ComparisonPage tabpanels. Provider header (verified badge, name, location, rating, package name, price, CTA) + itemised sections with left-accent headings. Shadow (shadow-sm). Medium button. Reuses `ComparisonPackage` type from ComparisonTable. Shared by ComparisonPage V2 and V1 (extracted 2026-04-09). | -| ComparisonColumnCard | done | Card + Badge + Button + Divider + Typography + Tooltip + Link + StarRoundedIcon + VerifiedOutlinedIcon | Desktop column header card for ComparisonTable. Floating verified badge, recommended banner, provider name (truncated+tooltip), location, rating, package name, price, CTA, optional Remove link. Extracted from ComparisonTable (2026-04-12). | -| ComparisonTabCard | done | Card + Badge + Typography | Mobile tab rail card for ComparisonPage. Provider name + package name + price. Recommended badge in normal flow with negative margin overlap + brand glow. Fixed 210px width. Shared by V1 and V2 (extracted 2026-04-12). | - -## Organisms - -| Component | Status | Composed of | Notes | -|-----------|--------|-------------|-------| -| ServiceSelector | done | ServiceOption × n + Typography + Button | Single-select service panel for arrangement flow. Heading + subheading + ServiceOption list (radiogroup) + optional continue Button. Manages selection state via selectedId/onSelect. maxDescriptionLines pass-through. | -| PricingTable | planned | PriceCard × n + Typography | Comparative pricing display | -| PackageDetail | done | LineItem × n + Typography + Button + Divider | Right-side package detail panel. Warm header band (surface.warm) with "Package" overline, name, price (brand colour), Make Arrangement + Compare (with loading) buttons. Sections: Essentials + Optionals (before total) + total + Extras (after total, with subtext). `priceLabel` pass-through to LineItem (D039). T&C grey footer. Audit: 19/20. | -| ComparisonTable | done | Typography + Button + Badge + Link + Tooltip | Side-by-side package comparison CSS Grid. Sticky header cards with provider info + price + CTA. Row-merged sections (union of all items). 7 cell value types (discriminated union D036). Recommended column with warm bg + badge. Verified → "Make Arrangement", unverified → "Make Enquiry". ARIA table roles. Desktop only (mobile in ComparisonPage). Audit: 17/20. | -| FuneralFinder (V3) | done | Typography + Button + Divider + Select + MenuItem + OutlinedInput + custom StatusCard/SectionLabel | **Production version.** Hero search widget — clean form with status cards. Standard card container (surface.raised, card shadow). "How Can We Help" section: two side-by-side StatusCards (Immediate Need default-selected / Pre-planning) — white bg, neutral border, brand border + warm bg when selected, stack on mobile. "Funeral Type" Select + "Location" OutlinedInput with pin icon — standard outlined fields, no focus ring (per design). Overline section labels (text.secondary). CTA "Find Funeral Directors →" always active — validates on click, scrolls to first missing field. Required: status + location. Funeral type defaults to "show all". Dividers after header and before CTA. WAI-ARIA roving tabindex on radiogroup. aria-labelledby via useId(). Critique: 33/40 (Good). Audit: 18/20 (Excellent). | -| FuneralFinder V1 | archived | Typography + Button + Chip + Input + Divider + Link + custom ChoiceCard/TypeCard/CompletedRow/StepHeading | Archived — viewable in Storybook under Archive/. Stepped conversational flow. Audit: 14/20. Critique: 29/40. | -| FuneralFinder V2 | archived | Typography + Button + Input + Divider + Select + MenuItem + custom StepCircle | Archived — viewable in Storybook under Archive/. Quick-form with step circles. Audit: 18/20. Critique: 33/40. | -| FuneralFinder V4 | archived | Typography + Button + Input + Divider + Select + MenuItem + custom StepIndicator/FieldError | Archived. Based on V2 with: 3 numbered steps (48px circles, outline-to-fill + tick), ungated location field, no heading/subheading, "Search" CTA, inline copper error messages. | -| ArrangementForm | planned | StepIndicator + ServiceSelector + AddOnOption + Button + Typography | Multi-step arrangement wizard. Deferred — build remaining atoms/molecules first. | -| Navigation | done | AppBar + Link + IconButton + Button + Divider + Drawer | Responsive site header. Desktop: logo left, links right, optional CTA. Mobile: hamburger + drawer with nav items, CTA, help footer. Sticky, grey surface bg (surface.subtle). Real FA logo from brandassets/. Maps to Figma Main Nav (14:108) + Mobile Header (2391:41508). | -| Footer | done | Link × n + Typography + Divider + Container + Grid | Light grey (surface.subtle) site footer — matches header. Logo + tagline + contact (phone/email) + link group columns + legal bar. Semantic HTML (footer, nav, ul). Critique: 38/40 (Excellent). | - -## Templates - -| Component | Status | Composed of | Notes | -|-----------|--------|-------------|-------| -| WizardLayout | done | Container + Box + Link + Typography + Navigation (slot) + StepIndicator (slot) | Page-level layout for arrangement wizard. 5 variants: centered-form, list-map, list-detail, grid-sidebar, detail-toggles. Nav slot, sticky help bar, optional back link, optional progress stepper + running total. `
` landmark wrapper. | - -## Pages - -| Component | Status | Composed of | Notes | -|-----------|--------|-------------|-------| -| IntroStep | done | WizardLayout (centered-form) + ToggleButtonGroup × 2 + Collapse + Typography + Button + Divider | Wizard step 1 — entry point. forWhom (Myself/Someone else) + hasPassedAway (Yes/No) with progressive disclosure. Auto-sets hasPassedAway="no" for "Myself". `
` wrapper, aria-live subheading, grief-sensitive copy. Pure presentation. Audit: 18/20 → 20/20 after fixes. | -| ProvidersStep | done | WizardLayout (list-map) + ProviderCard + SearchBar + Chip + Typography + Button | Wizard step 2 — provider selection. List-map split: provider cards w/ radiogroup + search + filter chips (left), map slot (right). aria-live results count, back link. ProviderCard extended with HTML/ARIA passthrough. Audit: 18/20. | -| PackagesStep | done | WizardLayout (list-detail) + ProviderCardCompact + ServiceOption + PackageDetail + Badge + TextField + Typography + Button | Wizard step 3 — package selection. List-detail split: compact provider + budget filter + package list w/ radiogroup (left), PackageDetail breakdown (right). "Most Popular" badge. Mobile Continue button. | -| ~~PreviewStep~~ | removed | — | Replaced by ArrangementDialog organism (D-E). Package preview + "what's next" checklist now in the dialog's preview step. | -| ~~AuthGateStep~~ | removed | — | Replaced by ArrangementDialog organism (D-E). SSO/email auth flow now in the dialog's auth step. | -| DateTimeStep | done | WizardLayout (centered-form) + Input + TextField (date) + RadioGroup + Collapse + Divider + Button + Link | Wizard step 6 — details & scheduling. Deceased name (Input atom, external label) + preferred dates (up to 3, progressive disclosure) + time-of-day radios. Service tradition removed (flows from provider/package). Dividers between sections. Grief-sensitive labels. Save-and-exit CTA. | -| VenueStep | done | WizardLayout (centered-form) + VenueCard + AddOnOption + Collapse + Chip + TextField + Divider + Button | Wizard step 7a — venue browsing. Click-to-navigate card grid with search/filters. Leads to VenueDetailStep. | -| VenueDetailStep | done | WizardLayout (detail-toggles) + ImageGallery + Card + Chip + Typography + Button + Divider | Wizard step 7b — venue detail. Two-panel: gallery/description/features/location (left), name/meta/price/CTA/religions (right). Informational service preview. | -| VenueServicesStep | done | WizardLayout (centered-form) + AddOnOption + Card + Typography + Button + Divider | Wizard step 7c — venue services. Compact venue card, availability notices, AddOnOption toggles with "View more" for long descriptions. Follows VenueDetailStep. | -| CrematoriumStep | done | WizardLayout (centered-form) + Card + Badge + ToggleButtonGroup + Typography + Button + Divider | Wizard step 8 — crematorium. Two variants: Service & Cremation (compact card + witness Yes/No toggle), Cremation Only (compact card + "Cremation Only" badge + "Included in Package" notice). Single pre-selected crematorium, no multi-select. | -| CemeteryStep | done | WizardLayout (centered-form) + ToggleButtonGroup + Collapse + TextField (select) + Typography + Button + Divider | Wizard step 9 — cemetery. ToggleButtonGroups (Yes/No/Not sure) with progressive disclosure. Own plot → locate dropdown. No plot → preference? → select dropdown. No card grid. | -| CoffinsStep | done | WizardLayout (grid-sidebar) + Card + Badge + Collapse + Slider + TextField + Pagination + Divider + Link | Wizard step 10 — coffin browsing. Grid-sidebar: filter sidebar (categories with expandable subcategories, dual-knob price slider with editable inputs, sort by) + 3-col card grid. CoffinCard with thumbnail hover preview. Equal-height cards, subtle bg for white-bg product photos. Card click → CoffinDetailsStep (no Continue). 20/page max. Conditional allowance info bubble. | -| CoffinDetailsStep | done | WizardLayout (detail-toggles) + ImageGallery + Divider + Button | Wizard step 11 — coffin detail. Two-panel: gallery + product details dl (left), name + description + colour swatches + allowance-aware price + CTA (right). Allowance logic: fully covered / partially covered / no allowance. Colour selection does not affect price. | -| ~~AdditionalServicesStep~~ | removed | — | Replaced by IncludedServicesStep + ExtrasStep. Split for clearer distinction between free inclusions and paid extras. | -| IncludedServicesStep | done | WizardLayout (centered-form) + AddOnOption + RadioGroup + Collapse + Divider + Button | Wizard step 12a — included services. Package inclusions at no additional cost: dressing, viewing (with same-venue sub-option), prayers/vigil, funeral announcement. Sub-options render inside parent card. | -| ExtrasStep | done | WizardLayout (centered-form) + AddOnOption + Card + Switch + RadioGroup + Collapse + Divider + Button | Wizard step 12b — optional extras. Lead-gen interest capture: catering, music (inline live musician toggle + musician type), coffin bearing (toggle + bearer type), newspaper notice. POA via `priceLabel`. Tally of priced selections. No nested cards. | -| SummaryStep | done | WizardLayout (centered-form) + Card + Paper + DialogShell + Button + Link + Divider | Wizard step 13 — plan review. Visual cart layout: arrangement details (2-col grid), compact cards with thumbnails for provider/venue/crematorium/coffin, checklist for included services, priced list for extras. Allowance display (fully covered vs remaining). Share dialog (multi-email). Location pin icons. Full-width CTA. | -| PaymentStep | done | WizardLayout (centered-form) + ToggleButtonGroup + Paper + Collapse + Checkbox + Divider + Button | Wizard step 14 — payment. Plan (full/deposit) + method (card/bank). PayWay iframe slot. Bank transfer details. Terms checkbox. | -| ConfirmationStep | done | WizardLayout (centered-form) + Button | Wizard step 15 — confirmation. Terminal page. At-need: "submitted" + callback. Pre-planning: "saved" + return-anytime. Muted success icon. | -| UnverifiedProviderStep | done | WizardLayout (list-detail) + ProviderCardCompact + ProviderCard + Badge + Button + Divider + Typography | Unverified provider detail. Left: compact card + "Listing" badge + available info (conditional dl) + verified recommendations. Right: warm header band + detail rows + "Make an Enquiry" CTA. Graceful degradation (no data → straight to enquiry). 4 story variants. | -| HomePage | done | FuneralFinderV3/V4 (via finderSlot) + ProviderCardCompact + Button + Typography + Accordion + Divider + Navigation (prop) + Footer (prop) | Marketing landing page. 4 archived versions: V1 (split hero), V2 (full-bleed parsonshero.png), V3 (hero-3.png + updated copy + logo bar + venue photos + warm CTA gradient), V4 (same as V3 but with FuneralFinderV4 stepped form via finderSlot). `finderSlot` prop allows swapping finder widget. Light grey footer (surface.subtle). | -| ComparisonPage (V2) | done | WizardLayout (wide-form) + ComparisonTable + Card + Typography + Button + Divider + StarRoundedIcon | **Production version.** Package comparison page. Desktop: full ComparisonTable with sticky headers, **recommended package as first (leftmost) column**. Mobile: tabbed card view with horizontal tab rail (role="tablist") + single package card (role="tabpanel"); **recommended tab is first in rail, first user-selected package is initially active**. Recommended package as separate prop (D038). Star icon (brand-600) marks recommended in mobile tab labels. Share + Print in page header. Back link, help bar. | -| ComparisonPage V1 | archived | WizardLayout + ComparisonTable + Card + Typography + Button + Divider | Archived — viewable in Storybook under Archive/. Recommended package as **last** column/tab. Same component tree as V2. | - -## Future enhancements - -Deferred items that should be addressed when the relevant components or patterns -are needed. Check this section before building new components — an item here may -be relevant to your current work. - -| Item | Relates to | Trigger | Notes | -|------|-----------|---------|-------| -| Destructive button colours | Button | When building delete/cancel flows | `color="error"` already works via MUI palette. May need `soft` variant styling for error/warning/success colours. | -| Link-as-button | Button | When building Navigation or link-heavy pages | Use MUI's `component="a"` or `href` prop. May warrant a separate Link atom or a `Button` story showing the pattern. | -| ~~IconButton atom~~ | ~~IconButton~~ | ~~Resolved~~ | ~~Built as atom. Rounded rect, 3 sizes, 4 colours, focus ring.~~ | -| ~~Google Fonts loading~~ | ~~Typography~~ | ~~Resolved~~ | ~~Added to .storybook/preview-head.html and index.html~~ | diff --git a/docs/memory/session-log.md b/docs/memory/session-log.md deleted file mode 100644 index 3b102a4..0000000 --- a/docs/memory/session-log.md +++ /dev/null @@ -1,1136 +0,0 @@ -# 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. - -> Earlier sessions (2026-03-24 through 2026-03-26d) archived in -> `docs/memory/archive/sessions-through-2026-03-26.md` - -## 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-04-13 — Chromatic image hosting + Gitea domain migration - -**Agent(s):** Claude Opus 4.6 (1M context) - -**Work completed:** -- **Gitea domain migration** — updated all remotes (backup, fa-dev) and references from `git.richie-snitch.online` to `git.tensordesign.com.au`. Updated publish skill and memory files. -- **Chromatic image hosting solution** — created `src/utils/assetUrl.ts` utility that resolves image paths via `STORYBOOK_ASSET_BASE` env var. When set (Chromatic builds), images load from Gitea ParsonsAssets repo. When empty (local dev), paths resolve via staticDirs as before. -- **Fixed path inconsistency** — story files used `/brandassets/images/...` which only worked locally via Vite root serving, not in builds. Changed to `/images/...` (correct for staticDirs) wrapped in `assetUrl()`. -- **Updated 4 files:** HomePage.tsx, HomePageV2.stories.tsx, HomePageV3.stories.tsx, HomePageV4.stories.tsx -- **Updated publish skill** — added Step 4 (sync assets to Gitea) and Step 5 (Chromatic with STORYBOOK_ASSET_BASE env var) -- **Created init script** — `scripts/init-assets-repo.sh` for one-time setup of ParsonsAssets repo on Gitea - -**Decisions made:** -- ParsonsAssets Gitea repo must be **public** so Chromatic clients can load images without auth -- `/brandlogo/` SVG paths left as-is — they're small, tracked in git, and work via staticDirs in builds -- Only `/brandassets/images/...` paths converted to `assetUrl()` — these are the large untracked binaries -- Scripts directory gitignored (contains embedded credentials) - -**Open questions:** -- User needs to create ParsonsAssets repo on Gitea and run `scripts/init-assets-repo.sh` (server not reachable from dev machine) - -**Next steps:** -- Create public ParsonsAssets repo on git.tensordesign.com.au -- Run init script to push 1.1GB of brand assets -- Test `/publish` end-to-end to verify Chromatic images render - ---- - -### Session 2026-04-12b — Homepage V3 redesign + FuneralFinder refinements - -**Agent(s):** Claude Opus 4.6 (1M context) - -**Work completed:** -- **HomePage V3 promoted to production** — story title changed from `Archive/HomePage V3` to `Pages/HomePage` -- **FuneralFinder V3 refinements:** responsive CTA (medium on mobile, large on desktop), button text "Search Local Providers" → "Search", "Free to use" bumped from captionSm to caption, tightened location pin-to-text gap -- **New section: "Why Use Funeral Arranger"** — text left + image right (people.png), overline + display3 heading + body copy -- **New section: "Three ways we can help you today"** — 3 feature cards with placeholder images, headings, descriptions, outlined CTA buttons -- **Section reorder:** partner logos carousel moved above Discover section, inherits overlap padding from FuneralFinder -- **Background colour scheme from Figma Make:** warm-grey alternating — `#f3efea` (darkest), `#fdfbf9` (lightest), `#f8f5f1` (mid), white sections with `#f3efea` borders -- **Overline headings** ("WHY USE FUNERAL ARRANGER", "WHAT YOU CAN DO HERE") styled in copper brand-600 -- **Card drop shadows** on three feature cards (shadow-md, removed border) -- **Heading consistency:** all section headings unified to display3 serif; "Why Use FA" was h3, FAQ was h2 — both fixed -- **SEO fixes:** h1 grammar ("funeral directors pricing" → "funeral director pricing"), logo section heading `

` → `

`, `aria-labelledby` on partner section -- **Section padding** increased from py 8/12 to 10/14 across all sections -- **Testimonials** left-aligned with consistent 560px max-width, centred block -- **"See more" button** added below FAQ accordion -- **FAQ heading** changed to "Frequently Asked Questions" -- **Logo section** changed to white bg, overline style heading, increased heading-to-logos gap -- **Figma capture** sent to Parsons Figma file (node 6049-25005) - -**Decisions made:** -- Page-level warm-grey backgrounds use direct hex values (#f3efea, #fdfbf9, #f8f5f1) rather than brand tokens — brand-100 (#f7ecdf) is too golden; the Figma tones are neutral-warm -- All section headings use display3 (Noto Serif SC) visually, rendered as semantic h2 tags -- Three feature card buttons are outlined, text-only (no arrows) - -**Next steps:** -- Replace feature card placeholder images with real screenshots/illustrations -- Wire up onClick handlers for feature card CTAs and FAQ "See more" when routing is in place -- Consider meta title/description for production deployment - ---- - -### Session 2026-04-12 — ComparisonPage refinements + new molecules - -**Agent(s):** Claude Opus 4.6 (1M context) - -**Work completed:** -- **New molecule** `ComparisonColumnCard` — extracted ~150 lines of desktop column header JSX from ComparisonTable. Floating verified badge, recommended banner, provider info, price, CTA, Remove link. Stories: Verified, Unverified, Recommended, LongName, NoRating, SideBySide. -- **New molecule** `ComparisonTabCard` — extracted mobile tab rail card from ComparisonPage. Provider name + package name + price. Recommended badge in normal flow (not absolute, avoids overflow clipping). Brand glow for recommended. Fixed 210px width. Stories: Default, Active, Recommended, RecommendedActive, LongName, Rail. -- **CellValue "unknown" restyled** — changed from Badge to icon+text (like Complimentary but in neutral.500 grey). InfoOutlinedIcon on the right at 14px, matching the item info icons. Both desktop (ComparisonTable) and mobile (ComparisonPackageCard) renderers updated. -- **Unverified provider story data** — all three story files (ComparisonTable, ComparisonPage, ComparisonPageV1) updated: Inglewood (unverified) shows `unknown` for every item across all sections. No more dashes in essentials for unverified providers. -- **Mobile tab rail overhaul:** - - Recommended badge (replaces star icon), in normal document flow with `mb: -10px` overlap - - Package price shown on each tab card in brand colour - - Shadow on all cards (`shadow-sm`), brand glow on recommended (`0 0 12px`) - - Center-on-select scroll behaviour, user's first package centered on mount - - Overflow clipping fixed via padding approach (`px: 2, mx: -2`) + normal-flow badge -- **ComparisonPackageCard** — added `shadow-sm`, reduced CTA button from `large` to `medium` -- **ComparisonTable** — removed ~150 lines of inline header card JSX, 5 unused imports -- **Both ComparisonPage V1 and V2** updated to use new molecules (ComparisonTabCard, ComparisonColumnCard via ComparisonTable) -- **Registry updated:** added ComparisonColumnCard and ComparisonTabCard rows, updated ComparisonPackageCard notes -- **Preflight:** tsc ✓, eslint ✓, prettier ✓ - -**Decisions made:** -- Unknown cell type uses InfoOutlinedIcon (not HelpOutlineIcon) — matches the info icons on item names in the first column for visual consistency -- Dashes (unavailable) reserved for optionals/extras where a provider doesn't offer that item; essentials always show unknown for unverified providers -- Mobile tab rail badge uses normal document flow (not absolute positioning) to avoid overflow clipping from `overflow-x: auto` -- Tab rail centres selected card (not scroll-to-left) -- ComparisonTabCard fixed at 210px width - -**Next steps:** -- User starting a new session - ---- - -### Session 2026-04-09b — Extract ComparisonPackageCard molecule - -**Agent(s):** Claude Opus 4.6 (1M context) - -**Work completed:** -- **New molecule** `src/components/molecules/ComparisonPackageCard/` — extracted from the duplicated `MobilePackageCard` + `MobileCellValue` helpers that lived inline in both V1 and V2. - - API: `{ pkg: ComparisonPackage, onArrange, sx }` — reuses the existing `ComparisonPackage` type from ComparisonTable - - Stories: Verified (default), Unverified, Recommended, ItemizedUnavailable — rendered in a 400px-max wrapper via decorator - - Full forwardRef + displayName -- **V2 ComparisonPage.tsx:** removed ~250 lines of inline helpers + 7 now-unused imports (Tooltip, InfoOutlinedIcon, CheckCircleOutlineIcon, LocationOnOutlinedIcon, VerifiedOutlinedIcon, Badge, Divider, ComparisonCellValue type). Imports ComparisonPackageCard and uses it in the mobile tabpanel. -- **V1 ComparisonPageV1.tsx:** same cleanup as V2. -- **Registry updated:** added ComparisonPackageCard row to molecules table. -- **Preflight:** tsc ✓, eslint ✓, prettier ✓ (one auto-format pass on new molecule), storybook build ✓. - -**Why:** User anticipated frequent card-level tweaks and didn't want to make each edit twice (V1 + V2). Extraction creates one source of truth for the mobile comparison card layout. - -**Decisions made:** -- Kept the desktop column header (in ComparisonTable) inline — it's tightly coupled to the grid/sticky layout and has a floating verified badge + Remove link that differ from the mobile card variant. Extracting it would create an awkward shared API for marginal gain. -- Did not create a shared `formatPrice` util — kept one local copy in the molecule (and one that still exists in ComparisonTable). That's a separate cleanup for later if it becomes painful. - -**Next steps:** -- Client review of ComparisonPage V2 still pending -- Possible future extract: ComparisonColumnHeader (desktop) if reused outside comparison - ---- - -### Session 2026-04-09 — ComparisonPage V2 (recommended-left) for client review - -**Agent(s):** Claude Opus 4.6 (1M context) - -**Work completed:** -- **Archived V1** — copied `ComparisonPage.tsx` → `ComparisonPageV1.tsx`, renamed component + displayName, created `ComparisonPageV1.stories.tsx` with title `Archive/ComparisonPage V1`, exported both from `index.ts`. -- **Built V2 (new production):** - - Desktop: recommended package now prepends to `allPackages` → appears as the **first (leftmost)** column in ComparisonTable - - Mobile tab rail: recommended is the **first tab**, but `defaultTabIdx = recommendedPackage ? 1 : 0` — the **first user-selected package is the initially active tab**, not the recommended - - JSDoc updated to reflect V2 behaviour and reference V1 archive -- **Better star for mobile tab rail (applied to both V1 and V2):** - - Replaced `★ ${provider.name}` text star with `StarRoundedIcon` (brand-600, 16px) - - Icon sits in a flex row with the provider name, `flexShrink: 0` so it always renders, aria-label="Recommended" - - Visible against both the selected tab state (warm bg) and unselected (white bg) -- **Memory updates:** component-registry (V1 archived, V2 production), decisions-log D040 (recommended-left rationale, supersedes D038 placement), this session entry -- **Preflight:** tsc ✓, eslint ComparisonPage dir ✓, prettier ✓ - -**Decisions made:** -- D040: Recommended appears on left (desktop), first in rail (mobile), but first user package is initially active on mobile — anchors comparison without hard-upselling in grief-sensitive context - -**Open questions:** -- None — awaiting client review feedback - -**Next steps:** -- Client review of V2 today -- If approved, remove V1 archive after a safe rollback window -- Remaining roadmap items: wire CompareBar into PackagesStep/ProvidersStep, comparison state persistence - ---- - -### Session 2026-04-07 — Package comparison iteration (Figma-informed) - -**Agent(s):** Claude Opus 4.6 (1M context) - -**Work completed:** -- **ComparisonTable major iteration** from Figma feedback: - - Dark info card → soft grey info card (surface.subtle, no border), stretches to match card heights, text at top - - Provider cards: no logos, floating verified badge (VerifiedOutlinedIcon, consistent with ProviderCard/MiniCard/MapPopup), rating in cards (body2 size) - - Separate bordered tables per section (Essentials, Optionals, Extras) with left accent borders (3px brand-500) - - Reviews section removed (rating lives in cards) - - Horizontal scroll on narrow desktops (minWidth enforcement) - - Cards: flex stretch + spacer for CTA bottom-alignment across mixed verified/unverified - - Row hover highlight (brand-50), font hierarchy (labels text.secondary, values fontWeight 600) -- **ComparisonPage iteration:** - - Share + Print buttons in page header (onShare, onPrint props) - - Mobile verified badge (VerifiedOutlinedIcon in soft brand Badge) - - Mobile section headings with left accent borders - - Mobile item rows: 60% max-width for names, inline info icons with nowrap binding - - Mobile tab rail: mini Card components (provider name + package name) replacing Chips - - Navigation included by default in all stories -- **CompareBar simplified:** - - Fraction badge (1/3, 2/3, 3/3) - - Contextual copy: "Add another to compare" / "Ready to compare" - - Removed package names and remove buttons from pill -- **Figma integration:** - - Created `/capture-to-figma` skill — captures Storybook stories to Parsons Figma file - - Created `/figma-ideas` skill — fetches Figma designs and proposes adaptations - - Successfully captured ComparisonPage to Figma (node 6041-25005) - - Applied user's Figma tweaks (node 6047-25005) back to code -- **Cleanup:** Removed Figma capture script from preview-head.html, Prettier formatting pass - -**Decisions made:** -- Info card uses surface.subtle (not dark), stretches to match cards — less visually competing -- Verified badge uses VerifiedOutlinedIcon (consistent with rest of system), floating above cards -- Rating lives in card headers, no separate Reviews table -- Section tables separated with left accent borders (3px brand-500) -- Mobile tab rail uses mini Cards (provider + package name) not Chips -- Share/Print are optional props on ComparisonPage - -**Next steps:** -- Commit all work -- Wire CompareBar into PackagesStep/ProvidersStep (state management) -- Consider comparison state persistence (URL params or context) - ---- - -### Session 2026-04-06b — Package comparison feature - -**Agent(s):** Claude Opus 4.6 (1M context) - -**Work completed:** -- **PackageDetail fix (D039):** Added `priceLabel?: string` to `PackageLineItem` interface, passed through to LineItem. Updated stories to use Essentials/Optionals/Extras sections with realistic funeral data (D035). "Complimentary Items" → "Optionals". -- **CompareBar molecule (new):** Floating comparison basket pill. Fixed bottom, slide-up/down animation. Badge count + provider names + remove × buttons + Compare CTA. Max 3 user packages. Disabled CTA when <2. Inline `role="alert"` error for max-reached. Mobile: compact count + CTA only. Audit: 18/20 (P2s fixed: error visible on mobile, removed redundant aria-disabled). -- **ComparisonTable organism (new):** CSS Grid side-by-side comparison. Sticky header cards with provider logo/name/location/rating + package name + price + CTA. Row-merged sections via `buildMergedSections` union algorithm. 7 cell value types via discriminated union (D036). Recommended column with warm bg + Badge. Verified → "Make Arrangement", unverified → "Make Enquiry". ARIA `role="table"` + `role="row"` + `role="columnheader"` + `role="cell"`. Desktop only. Audit: 17/20 (P2s fixed: aria-label on recommended column, rowheader on section headings, token-based zebra striping). -- **ComparisonPage page (new):** WizardLayout (wide-form). Desktop: full ComparisonTable. Mobile: chip tab rail (`role="tablist"`) + single MobilePackageCard (`role="tabpanel"`). Recommended package as separate prop, merged as last column/tab. Back link, help bar. -- **Stories:** 6 CompareBar stories (Default, SinglePackage, ThreePackages, WithError, Empty, Interactive), 5 ComparisonTable stories (Default, TwoPackages, WithRecommended, MixedVerified, MissingData), 5 ComparisonPage stories (Default, TwoPackages, WithRecommended, MobileView, FullPage with Navigation). -- **Quality gates:** TypeScript ✓, ESLint ✓, Storybook build ✓. CompareBar audit 18/20, ComparisonTable audit 17/20. - -**Decisions made:** -- D035: Package sections standardised to Essentials/Optionals/Extras -- D036: ComparisonCellValue uses discriminated union for exhaustive rendering -- D037: Mobile comparison uses chip tabs + card view, not horizontal scroll table -- D038: Recommended package is a separate prop, always additional to user selections -- D039: PackageLineItem gains priceLabel for consistency with LineItem molecule - -**Open questions:** -- None - -**Next steps:** -- Visual review in Storybook (user + Playwright screenshots) -- Wire CompareBar into PackagesStep (state management for comparison basket) -- Consider adding CompareBar to WizardLayout as a slot or portal - ---- - -### Session 2026-04-06 — Retroactive review completion - -**Agent(s):** Claude Opus 4.6 (1M context) - -**Work completed:** -- **Phase 1 atoms complete:** Audited Typography (18/20, no P0/P1) and Badge (15/20, P0 `role="status"` determined false positive — would create unwanted aria-live on static labels) -- **Phase 2 molecules complete:** Normalized all 9 molecules — displayName ✓, forwardRef ✓, ARIA ✓, no hardcoded colours. Flagged AddOnOption/ProviderCard ARIA issues reviewed and determined false positives (Switch is semantic control; ProviderCard has `...rest` passthrough) -- **Phase 3 organisms complete:** Normalized 5 active organisms. Audited Navigation (15/20, no real P0/P1 — focus-visible from MUI theme, CSS vars D031-compliant) and ServiceSelector (17/20, **fixed P0: added `aria-required` to radiogroup**) -- **Phase 4 preflight:** TypeScript ✓, ESLint ✓, Prettier ✓, Storybook build ✓ -- **Review plan updated:** All phases marked done. Only `/typeset` deferred (low risk) - -**Decisions made:** -- Badge `role="status"` rejected: static status labels shouldn't be aria-live regions -- AddOnOption `role="checkbox"` rejected: Switch is the semantic control, Card click is convenience -- CSS var usage in organisms is D031-compliant (CSS vars acceptable for semantic tokens per D031) - -**Open questions:** -- From 2026-04-01: Which HomePage version (V3 or V4) is production? - -**Next steps:** -- User has components to change/build — shifting to that work - -**Work completed (continued):** -- **MiniCard molecule (new + iterated):** Compact vertical card. Image + verified icon-only badge (copper circle, top-right) + title (h6, 2-line max with tooltip on truncation) + meta row + price + badges + chips. Hierarchy: title → meta → price → badges → chips. 3 component tokens. Audit: 20/20. -- **MapPin atom (new + redesigned):** Two-line label map marker: name (bold, truncated 180px) + "From $X" (centred, semibold 600). Name optional for price-only variant. Verified = brand palette, unverified = grey. Active inverts + scale. Padding bumped from 8px to 12px for readability. Pure CSS. role="button" + keyboard + focus ring. -- **MapPopup molecule (new + iterated):** Clickable floating card (onClick). Image + verified icon badge (matches MiniCard) + name (1-line, tooltip on truncation) + meta + price. Hierarchy matches MiniCard. No-image fallback shows inline verified icon + text. Nub + drop-shadow. 260px wide. -- **Component tokens:** miniCard.json and mapPin.json added to Style Dictionary, rebuilt CSS/JS/TS outputs (407 declarations total). - -**Decisions made:** -- MiniCard uses `h6` for title (smaller than ProviderCard's `h5`), `caption` for meta, `body2` for price -- MiniCard verified badge is icon-only circle (not text chip) — compact, matches map popup -- MapPin redesigned from price-only pill to two-line name+price label — transparency and clarity -- MapPin price centred under name — left-aligned looked unbalanced (visually reviewed) -- MapPin price weight 600 (semibold) — 500 was too thin at 11px -- MapPin padding 12px (was 8px) — names were tight against edges -- MapPopup whole card clickable — removed "View details" link -- MapPopup name 1-line limit (was 2) with tooltip — tighter for map context -- Chips in MiniCard rendered as soft default Badges (no interactive Chip atom) for visual simplicity - ---- - -### Session 2026-04-01 — FuneralFinder V4, HomePage V3/V4, Footer restyle - -**Agent(s):** Claude Opus 4.6 (1M context) - -**Work completed:** -- **FuneralFinder V4 (new organism):** Based on V2 with major changes: - - 3 numbered steps only (lookingTo, planningFor, funeralType) — location is ungated, no step number - - No heading/subheading — compact widget for embedding in heroes - - Refined step indicators: 48px circles matching input height, outline-to-fill + tick animation, no connector lines - - Labels above, circle + input on same row centred - - Location field full-width, disabled until step 3 complete - - "Search" CTA, inline copper error messages per field (D034) - - Archived in Storybook under Archive/FuneralFinder V4 -- **FuneralFinder V3 updates:** - - Removed default subheading (now optional) - - Heading font weight bumped from 400 → 600 (semibold) for more presence - - Heading copy: "Find your local providers" - - CTA: "Search Local Providers" -- **HomePage V1 archived:** Original split-hero layout moved to Archive/HomePage V1 -- **HomePage V2 archived:** Full-bleed hero version broken out as Archive/HomePage V2 -- **HomePage V3 (new, archived):** Based on V2 with: - - hero-3.png background image - - Updated hero copy + bullet-point subheading ("Transparent pricing · No hidden fees · Arrange 24/7") - - Real venue photos in discover section provider cards - - Map placeholder image from brandassets - - Scrolling partner logo bar (9 transparent logos, greyscale, edge-to-edge, continuous loop) - - CTA section: warm gradient bg, text button, no dividers, wider container - - Increased section spacing throughout (~25% more breathing room) - - Hero top padding increased 40% -- **HomePage V4 (new, archived):** Same as V3 but uses FuneralFinder V4 via `finderSlot` prop. Wider container (620px) for stepped form. -- **HomePage component updates:** - - Added `finderSlot` prop — allows swapping the finder widget without changing the component - - Increased spacing: hero heading/subtext gap, finder-to-discover gap, all section padding - - Map container: absolute positioning for dynamic height matching card stack - - CTA section: gradient bg (brand.100 → surface.warm), text button, no dividers - - Partner logos: lighter treatment (40% opacity, brightness lift), 48→55px height, 96px gap, no hover interaction -- **Footer restyle:** Changed from dark espresso (brand.950) to light grey (surface.subtle) matching the header. All text colours flipped to dark-on-light. Logo no longer needs inverse filter. - -**Decisions made:** -- FuneralFinder V4 step indicators use 48px circles (same height as inputs) for visual alignment -- Location field in V4 is gated behind step 3 completion but not numbered -- Inline error messages replace single bottom error — each field shows its own copper-coloured message -- Footer matches header bg colour (surface.subtle) for visual consistency -- Partner logos: only transparent PNGs/WebPs used, opaque logos excluded -- `finderSlot` prop added to HomePage for widget flexibility without component duplication - -**Open questions:** -- HomePage V4 finder width may need further adjustment — looked narrow in Storybook preview panel (620px container, may need 680-720px) -- Which HomePage version (V3 with FuneralFinderV3 or V4 with FuneralFinderV4) will be the production version? -- FuneralFinder V4 step indicator design — user liked the direction but may want further iteration - -**Next steps:** -- Resolve HomePage V4 finder width — test at wider viewport or increase container -- Decide on production HomePage + FuneralFinder version -- Build next components/pages as needed -- Phase 4 remaining: /typeset sample, /preflight full codebase - ---- - -### Session 2026-03-31d — Filters, control bars, UnverifiedProviderStep, HomePage V2 - -**Agent(s):** Claude Opus 4.6 (1M context) - -**Work completed:** -- **Phase 4 /adapt reviews:** Ran responsive adaptation audits on Navigation, Footer, ProviderCard, VenueCard. Fixed P0/P1 touch target issues in Navigation (hamburger + drawer items minHeight 44px) and Footer (all links minHeight 44px, tagline responsive maxWidth). ProviderCard/VenueCard skipped — meta rows aren't interactive, card itself is the touch target. -- **ProvidersStep structured filters:** Replaced generic `ProviderFilter[]` chip array with `ProviderFilterValues` interface containing 5 filter controls inside FilterPanel/DialogShell: - - **Location:** Autocomplete `multiple` + `freeSolo` with chip-in-input pattern (real estate site UX — chip sits inside the search field with X to clear) - - **Service tradition:** Autocomplete with type-to-search, 21 options ('None' first, then alphabetical traditions) - - **Funeral type:** Chip multi-select with wrapping layout (6 types from spec) - - **Verified providers / Online arrangements:** Switch toggles - - **Price range:** Dual-knob slider + compact editable inputs (matching CoffinsStep) -- **FilterPanel molecule updates:** "Done" → "Apply", "Clear all" moved to footer as "Reset filters" text button -- **DialogShell padding:** px 3 → 5 (12px → 20px) for breathing room -- **Filter panel UX iterations (3 rounds):** - - Section headings: `labelLg` + `fontWeight: 600` for visual hierarchy - - Price inputs: compact `fontSize: 0.875rem` + tighter padding - - Funeral type chips: wrap layout (not horizontal scroll) — stays within bounds - - Price slider: `px: 2.5` accommodates MUI thumb radius, no overflow - - Active filter count includes location search; reset clears search too -- **VenueStep structured filters:** Same FilterPanel pattern as ProvidersStep with venue-specific controls: - - Location (chip-in-input), Venue type (7 chips: Chapel, Church, Cathedral, Outdoor Venue, Hall/Room, Mosque, Temple), Additional services (Video Streaming + Photo Display switches), Service tradition (autocomplete) -- **Control bar (both pages):** Below search, single line: - - `[Filters]` left, `[↕ Recommended]` right (compact menu button with dropdown) - - Sort options: Recommended, Nearest, Price: Low to High, Price: High to Low - - Results count on own line below with breathing room -- **List/Map view toggle:** Floating overlay in top-left of map panel (paper bg + shadow). Text-labelled: "List" / "Map" with icons. Follows Airbnb/Domain pattern — contextually placed where the map lives. -- New types: `ProviderSortBy`, `VenueSortBy`, `ListViewMode`, `VenueFilterValues`, `VenueTypeOption` -- **UnverifiedProviderStep (new page):** list-detail layout for scraped provider listings. Left: ProviderCardCompact + "Listing" badge + available info + verified recommendations. Right: warm header band + enquiry CTA. 4 story variants (Default, MinimalData, NoData, NoRecommendations). Graceful degradation when data missing. -- **HomePage V2:** Full-bleed hero with `parsonshero.png`, FuneralFinder inside hero (overlaps into white below), "See what you'll discover" map+ProviderCardCompact section, stripped features (no cards/circles — just icons+text), editorial alternating testimonials, minimal FAQ accordion, simplified CTA. Multiple iteration rounds on hero positioning. -- New types: `TrustStat`, `FeaturedProvider`, `ProviderDetail`, `RecommendedProvider` - -**Decisions made:** -- "Service tradition" as the label for religion/faith filter — neutral, user-centric, covers religious and non-religious -- 'None' as first tradition option -- Location uses Autocomplete chip-in-input pattern (Domain/realestate.com.au style) -- Funeral type chips wrap (stack) rather than horizontal scroll — clearer at dialog width -- DialogShell px: 5 is a global change — all dialogs get more breathing room -- FilterPanel footer: "Reset filters" + "Apply" replaces header "Clear all" + footer "Done" -- List/Map toggle lives on the map panel (floating overlay), not in the control bar — frees space, contextually placed -- Sort uses compact menu button (not TextField select) — same visual weight as Filters button -- Unverified providers use list-detail layout (same as PackagesStep) for consistency -- Unverified CTA is "Make an Enquiry" (not "Make an Arrangement") — honest framing -- HomePage V2 hero: text top-aligned, FuneralFinder inside hero with negative mb overlap -- Features section: no cards/circles — just icons + text for authentic feel -- Hero gradient: 55% opacity at top for readability on bright sky - -**Open questions:** -- HomePage V2 still a first pass — may iterate further on discover section, testimonials, etc. -- UnverifiedProviderStep paused — may revisit for enquiry form fields - -**Next steps:** -- Continue user feedback on remaining pages -- Phase 4 remaining: `/typeset` sample, `/preflight` full codebase -- Add progress bar + cart stories to more page stories -- Update component-registry.md with UnverifiedProviderStep - ---- - -### Session 2026-03-31c — PaymentStep/ConfirmationStep review + progress bar + CartButton - -**Agent(s):** Claude Opus 4.6 (1M context) - -**Work completed:** -- **Organism normalize pass (Phase 3):** Scanned all 6 organisms. Fixed FuneralFinderV3 transition timing (200ms → 150ms ease-in-out), added autodocs tag to V3 stories. Navigation audit 18/20, ServiceSelector 20/20. -- **Navigation P1 fix:** Logo wrapper changed from `div[role=link]` to proper `` tag for keyboard accessibility. -- **PaymentStep feedback (5 items):** Divider under subheading, lock icon alignment, ToggleButtonGroup `align` + `direction` props (centre-aligned payment options, vertical payment method stack), checkbox alignment fix. -- **ToggleButtonGroup atom enhanced:** New `align` (start/center) and `direction` (row/column) props. Description text bumped from `text.secondary` to `text.primary`. -- **SummaryStep:** Save button → text variant (matches other pages), centred. -- **Cross-page heading spacing:** All wizard pages `mb: 1` → `mb: 2` on display3 heading. -- **ConfirmationStep redesign:** Animated SVG tick (circle draws then checkmark), "What happens next" warm card with bullet points, contact phone as prop, link-based secondary actions. -- **VenueStep + ProvidersStep:** Sticky search bar padding fix, off-white bg behind card lists. -- **IntroStep, CemeteryStep, CrematoriumStep, DateTimeStep:** Dividers under subheadings. -- **CoffinsStep:** h4 heading (matches list layouts), sidebar headings h5 → h6. -- **CartButton molecule (new):** Outlined pill trigger with receipt icon + "Your Plan" + formatted total in brand colour. Click opens DialogShell with items grouped by section via LineItem, total row, empty state. Mobile collapses to icon + price. -- **WizardLayout:** Removed STEPPER_VARIANTS whitelist — stepper bar now renders on all variants when props provided. Stepper centred at 700px max-width, cart hugs right. -- **StepIndicator:** Desktop label fontSize bumped to 0.875rem for readability. -- **Prop threading:** progressStepper + runningTotal added to DateTimeStep, VenueStep, SummaryStep, PaymentStep. -- **Style Dictionary:** Auto-generate tokens.d.ts on build, fixed TS unused imports. - -**Decisions made:** -- ToggleButtonGroup `align` and `direction` are opt-in props — existing usages unchanged -- ConfirmationStep contact phone is now a prop (default 1800 987 888), no more hardcoded placeholder -- WizardLayout stepper bar shows on ANY variant when props provided (StepperBar returns null when empty) -- CartButton is a molecule (not organism) — self-contained trigger + dialog, same pattern as FilterPanel -- Stepper bar layout: stepper centred at maxWidth 700px, cart hugs right edge - -**Open questions:** -- PaymentStep CTA is right-aligned — all other pages use full-width. Should it match? -- Progress bar stories should be added to more page stories (currently only DateTimeStep has them) - -**Next steps:** -- Continue user feedback/edits on remaining pages -- Add progress bar + cart to remaining page stories -- Retroactive review Phase 3 organisms: Navigation P2s still pending (hardcoded fontSize, drawer width) -- Update component-registry.md with CartButton - ---- - -### Session 2026-03-31b — CoffinDetailsStep rewrite + AdditionalServicesStep split - -**Agent(s):** Claude Opus 4.6 (1M context) - -**Work completed:** -- **CoffinDetailsStep rewrite** — two-panel detail-toggles layout with gallery + specs (left), name + description + colour swatches + allowance-aware pricing + CTA (right). Colour selection doesn't affect price. Allowance logic: fully covered / partially covered / no allowance. -- **SummaryStep rewrite** — visual cart layout replacing accordion text lists: - - Arrangement details section at top (arranger, deceased, tradition, dates, times) - - Compact image cards for provider, venue, crematorium, coffin with location pins - - Allowance display: "Included in your package" (fully covered) vs price/allowance/remaining breakdown - - Checklist for included services, priced list for extras (consistent tick logic) - - Share dialog: "Share this plan" opens DialogShell with multi-email input + confirmation - - Full-width CTA, deposit deferred to PaymentStep -- **AdditionalServicesStep split into two pages:** - - **IncludedServicesStep (new)** — services included in the package at no cost. Dressing, viewing (with same-venue sub-option inside card), prayers/vigil, funeral announcement. - - **ExtrasStep (new)** — optional paid extras for lead generation. Catering, music (flat inline live musician toggle + musician type), coffin bearing (toggle + bearer preference radio), newspaper notice. POA support via `priceLabel`. Tally of priced selections. -- **AddOnOption molecule enhanced:** - - `children` prop — sub-options render inside the card boundary (below divider) when checked, eliminating nested card "Russian doll" pattern - - `priceLabel` prop — custom text like "Price on application" in brand copper italic -- **AdditionalServicesStep removed** — replaced by the two new pages -- All quality checks passing (TypeScript, ESLint, Prettier) -- Playwright visual verification of all key scenarios - -**Decisions made:** -- Split AdditionalServicesStep into two pages for clearer UX distinction between free inclusions and paid extras -- Sub-options render inside parent card (flat hierarchy) instead of nested cards -- Coffin bearing changed from always-visible radio to toggle + sub-options (consistent with other items) -- `bearing` field split into `bearing: boolean` + `bearerType` for toggle pattern -- Extras page is lead-gen: signals interest, not firm commitment. Director follows up. -- POA items show "Price on application" in brand copper italic -- Copy refined through brand lens — no transactional language ("toggle on"), warm professional tone - -**Open questions:** -- None - -**Next steps:** -- Continue page feedback: PaymentStep, ConfirmationStep -- Retroactive review Phase 3 (organisms) still pending -- Batch a11y fix (aria-describedby + aria-invalid) deferred - ---- - -### Session 2026-03-31b — CoffinDetailsStep rewrite: product detail layout - -**Agent(s):** Claude Opus 4.6 (1M context) - -**Work completed:** -- **CoffinDetailsStep complete rewrite** — transformed to match VenueDetailStep two-panel pattern: - - **Left panel:** ImageGallery (hero + thumbnails), product details as semantic `dl` list (bold label above value) - - **Right panel (sticky):** coffin name (h1), description, colour swatch picker, price with allowance-aware display, CTA, save-and-exit - - **Colour picker:** circular swatches (36px), `aria-pressed`, controlled via `selectedColourId`/`onColourChange`, does not affect price - - **Allowance pricing logic:** fully covered (allowance >= price) → "Included in your package allowance — no change to your plan total." / partially covered → shows "$X package allowance applied" + "+$Y to your plan total" in brand colour / no allowance → price only with extra spacing to CTA - - **Removed:** info bubble (redundant with allowance impact text), `priceNote` prop, `termsText` prop, old horizontal specs grid, `CoffinAllowance` type - - **Added:** `CoffinColour` type, `allowanceAmount` prop, `onAddCoffin` callback (replaces `onContinue`) - - **A11y:** fixed heading hierarchy (price as `

` not `

`, Product details as `

`) — 0 violations -- **Stories:** FullyCovered, PartiallyCovered, NoAllowance, NoColours, Minimal, PrePlanning, Loading -- **Playwright visual verification** of all key scenarios -- All quality checks passing (TypeScript, ESLint, Prettier) - -**Decisions made:** -- Allowance impact is computed from `allowanceAmount` vs `coffin.price` — no remaining balance tracking (out of scope) -- Info bubble removed from detail page (redundant) — kept on CoffinsStep browsing page -- Product details as single-column stacked `dl` (label above value) — more readable than grid - -**Open questions:** -- None - -**Next steps:** -- Continue page feedback: AdditionalServicesStep, SummaryStep, PaymentStep, ConfirmationStep -- Retroactive review Phase 3 (organisms) still pending -- Batch a11y fix (aria-describedby + aria-invalid) deferred - ---- - -### Session 2026-03-31a — CoffinsStep rewrite: grid-sidebar ecommerce layout - -**Agent(s):** Claude Opus 4.6 (1M context) - -**Work completed:** -- **CoffinsStep complete rewrite** — transformed from wide-form card grid into a two-column ecommerce layout matching the live site pattern: - - **Layout:** `grid-sidebar` with viewport-locked independent scrolling (sidebar scrollbar on hover, grid always scrollable) - - **Sidebar:** heading, conditional allowance info bubble, category menu with expandable subcategories (Collapse animation, chevron rotation), dual-knob price range slider with editable text inputs (commit on blur/Enter), sort by dropdown (popularity, price asc/desc), clear all filters link, save-and-exit link at bottom - - **Grid:** 3-col coffin card grid with `CoffinCard` internal component — thumbnail hover preview (hover swaps main image, leave reverts), equal-height cards via flex layout, subtle background for white-bg product photos, "Most Popular" badge, colour count text - - **Navigation:** card click fires `onSelectCoffin(id)` to navigate to CoffinDetailsStep — no Continue button - - **Pagination:** 20 coffins per page max (`pageSize` prop, enforced via slice) -- **WizardLayout `grid-sidebar` update** — wider sidebar (28%), `overflowX: hidden` (no horizontal scroll), `overflowY: auto` at all breakpoints, responsive viewport-lock (desktop only) -- **Removed:** `selectedCoffinId`, `CoffinsStepErrors`, `CoffinPriceRange`, `onContinue`, `loading` props -- **Added:** `onSelectCoffin`, `CoffinSortBy`, `pageSize`, `minPrice`/`maxPrice`, `thumbnails`/`colourCount` on Coffin, `children` on `CoffinCategory` - -**Decisions made:** -- Card click navigates directly to details (no selection + continue pattern) — matches ecommerce browsing UX -- Categories support one level of subcategories — parent click loads all and expands children, child click refines -- Price slider with editable text inputs — commits on blur/Enter to avoid per-keystroke re-renders -- 20 coffins per page default — enforced in component via slice -- Allowance info bubble is conditional (omit prop = no bubble) — some packages don't have coffin allowances - -**Open questions:** -- None - -**Next steps:** -- Continue page feedback: AdditionalServicesStep, SummaryStep, PaymentStep, ConfirmationStep -- Retroactive review Phase 3 (organisms) still pending -- Batch a11y fix (aria-describedby + aria-invalid) deferred - ---- - -### Session 2026-03-30e — Page feedback: VenueServices, Crematorium, Cemetery rewrites - -**Agent(s):** Claude Opus 4.6 (1M context) - -**Work completed:** -- **VenueServicesStep (new page):** Built step 7c — venue-specific service toggles after VenueDetailStep. Compact venue card at top, availability notices (info cards for unavailable services), AddOnOption toggles with maxDescriptionLines for "Read more" expansion, conditional tally showing total of selected priced services. Flow: VenueStep → VenueDetailStep → VenueServicesStep. -- **AddOnOption price colour fix:** Changed from `text.secondary` (grey) to `color="primary"` (copper) for consistency with all other price displays in the system. -- **CrematoriumStep rewrite:** Completely rewritten to match live site. Two variants based on funeral type: - - Service & Cremation: stacked crematorium card (image top, details below) + witness Yes/No/Decide later ToggleButtonGroup - - Cremation Only: stacked card + "Cremation Only" badge + "Included in Package" info notice, no witness question - - Removed: multi-card selection grid, priority dropdown, special instructions, crematoriums array prop - - Card iterated from compact horizontal → more generous horizontal → stacked layout based on user feedback -- **CemeteryStep rewrite:** Rewritten to match live site: - - RadioGroups replaced with ToggleButtonGroups (Yes/No/Not sure) - - Card selection grid replaced with freetext search input (Input atom with search icon) - - `searchSlot` prop for parent to inject Google Places or geocoding autocomplete - - Removed static `cemeteries` array prop and `CemeteryOption` type - - Progressive disclosure preserved: own plot → locate it; no plot → preference? → search - -**Decisions made:** -- Venue services belong on a separate page (not inline on VenueDetailStep or in a dialog) due to content volume per service (long descriptions, future images) -- Crematorium is always pre-selected by provider — no multi-select needed, just confirmation -- "Decide later" / "Not sure" options added as explicit third choice on questions where users may be uncertain — grief-sensitive pattern -- Cemetery search should use real location search (Google Places style), not a static dropdown — we don't maintain a cemetery database -- Stacked card layout (image top) works better than compact horizontal for single confirmation cards with long text - -**Open questions:** -- None - -**Next steps:** -- Continue page feedback: CoffinsStep, AdditionalServicesStep, SummaryStep, PaymentStep, ConfirmationStep -- Retroactive review Phase 3 (organisms) still pending -- Batch a11y fix (aria-describedby + aria-invalid) deferred - ---- - -### Session 2026-03-30d — Steps 8-15 consistency pass - -**Agent(s):** Claude Opus 4.6 (1M context) - -**Work completed:** -- **Consistency pass across Steps 8-15** — aligned all remaining wizard steps with the conventions established during the Steps 1-6 feedback iteration: - - **Subheading variant:** CrematoriumStep, CoffinDetailsStep changed from `body2` → `body1` (match IntroStep/DateTimeStep centered-form convention) - - **Subheading spacing:** CrematoriumStep, CemeteryStep, CoffinDetailsStep, AdditionalServicesStep, SummaryStep, PaymentStep all changed from `mb: 4` → `mb: 5` - - **Section dividers:** CrematoriumStep gained 3 `` between question sections (crematorium → witness, conditional priority, special instructions) - - **Link atom:** PaymentStep terms links and ConfirmationStep phone number changed from `Box component="a"` → `Link` atom - - **CoffinsStep:** No changes needed (wide-form layout has its own spacing convention) -- **Audited CrematoriumStep (15/20) and PaymentStep (16/20)** — findings are pre-existing, not introduced by the pass -- **Visual verification:** Playwright screenshots of CrematoriumStep, PaymentStep, ConfirmationStep, AdditionalServicesStep, SummaryStep — all pass - -**Decisions made:** -- Centered-form heading convention now formally: `display3` → `body1` subheading → `mb: 5` gap (documented via consistent implementation across all 10+ centered-form steps) -- Wide-form layout (CoffinsStep) keeps its own tighter spacing convention (`body2` + `caption`, `mb: 3`) - -**Open questions:** -- **Checkbox atom:** PaymentStep uses MUI Checkbox directly — only form control without an FA atom wrapper. Create Checkbox atom? -- **aria-describedby/aria-invalid:** All wizard steps lack error field association. Batch normalize fix recommended. -- **Retroactive review Phase 2.2** still pending (audit priority molecules: ServiceOption, AddOnOption, ProviderCardCompact) - -**Also completed (same session):** -- **Checkbox atom created:** New FA wrapper (forwardRef, displayName, stories: Default/States/TermsAgreement/Checklist). MuiCheckbox theme overrides (warm gold checked, focus ring, disabled muted). PaymentStep updated to import from atom. -- **Retroactive review Phase 2.2 complete:** Audited ServiceOption (13/20), AddOnOption (14/20), ProviderCardCompact (15/20). Fixed: - - AddOnOption: added `aria-disabled` when disabled (P1) - - ProviderCardCompact: added `maxLines={1}` on name (P2) - - ServiceOption: price uses `labelLg` variant instead of h6 + hardcoded fontWeight (P1) -- Note: audit agents flagged false P0s (AddOnOption "double handler", ServiceOption "role collision") — verified both are correctly handled by existing `stopPropagation` and prop spread order in Card atom - -**Also completed (continued same session):** -- **DateTimeStep:** Swapped date TextField to Input atom (was missed in session 30b) -- **VenueStep rewrite:** Simplified to click-to-navigate (like ProvidersStep) — removed Continue, selection state, inline detail, service toggles -- **VenueDetailStep (new page):** Detail-toggles layout with scrollable left panel (ImageGallery, description, features grid, location map placeholder, address, informational service cards) and right panel (name, meta icons, price + offset note, Add Venue CTA, address, religion chips) -- **CoffinDetailsStep:** Switched from centered-form to detail-toggles layout (image left, specs/price/CTA right) -- **WizardLayout detail-toggles overhaul:** Viewport-locked with independent panel scroll, maxWidth 1200px centered, generous padding (px:5), back link inside left panel -- **WizardLayout list-map scroll fix:** Removed top padding gap between nav and sticky search, heading scrolls away while search/filters stay pinned with divider border -- **ImageGallery molecule (new):** Hero image + landscape thumbnail strip (4:3 ratio), hover to preview, click to select, keyboard accessible, wired into VenueDetailStep and CoffinDetailsStep -- **Checkbox atom (new):** FA wrapper with warm gold theming, PaymentStep updated -- **Retroactive review Phase 2.2:** Audited ServiceOption (13/20), AddOnOption (14/20), ProviderCardCompact (15/20), fixed P0/P1s - -**Next steps:** -- Continue page feedback from user: CrematoriumStep, CemeteryStep, CoffinsStep, AdditionalServicesStep, SummaryStep, PaymentStep, ConfirmationStep -- Venue service selection step (new page — toggles moved from VenueDetailStep) -- Batch a11y fix: aria-describedby + aria-invalid across all wizard steps (deferred per user) -- Retroactive review Phase 3: organisms normalize + audit -- Update component registry with new components (ImageGallery, Checkbox, VenueDetailStep) - ---- - -### Session 2026-03-30c — HomePage build + Chromatic + Story to Design setup - -**Agent(s):** Claude Opus 4.6 (1M context) - -**Work completed:** -- **Story to Design agent:** Helped user install and run the story.to.design agent on Arch Linux (extracted from .deb, installed webkit2gtk dependency). Agent connects Storybook to Figma plugin. -- **Chromatic setup:** Installed chromatic, published Storybook to Chromatic CDN. Set visibility to public for shareable links. Updated `package.json` chromatic script with `--build-script-name=build:storybook`. -- **HomePage component built:** Full marketing landing page at `src/components/pages/HomePage/` - - 7 sections: Hero, FuneralFinder widget (overlapping card), Partner Logos carousel, Features (4-card grid), Reviews/Testimonials, CTA Banner, FAQ accordion - - Composes FuneralFinderV3 organism, Navigation + Footer via props - - CSS-only infinite scroll logo carousel with prefers-reduced-motion - - Feature cards with warm circular icon backgrounds - - Full a11y: section landmarks, aria-labelledby, heading hierarchy - - Grief-sensitive copy (quieter pass applied) -- **Quality gates run:** /critique (32/40), /audit (16/20), /quieter (all pass) -- **Design iteration:** Multiple rounds of visual refinement using Playwright screenshots - - Reduced oversized typography (display1 → display3 for hero, display2 → h2 for sections) - - Reserved serif fonts for hero + CTA only, sans-serif for all other section headings - - Tightened spacing, reduced section padding - - Feature cards: compact padding, warm circular icon backgrounds - - Fixed unicode rendering bugs in copy - -**Decisions made:** -- Serif display fonts reserved for hero heading and CTA banner only — all other section headings use Montserrat (h2/h3) -- Feature card icons wrapped in warm circular backgrounds (brand.50 bg, 56px diameter) -- HomePage is a page component (not a template) — does not use WizardLayout -- Chromatic published URL is the shareable Storybook link for stakeholders - -**Open questions:** -- Homepage is first-pass only — user will return to iterate later -- Partner logo placeholder images need real assets -- Hero image slot needs real photography -- CTA banner click destination needs clarification (scroll to widget vs wizard entry) - -**Next steps:** -- Resume arrangement wizard page feedback from VenueStep (Step 7) onwards — Steps 1-6 done in previous session -- Remaining pages: VenueStep, CrematoriumStep, CemeteryStep, CoffinsStep, CoffinDetailsStep, AdditionalServicesStep, SummaryStep, PaymentStep, ConfirmationStep - ---- - -### Session 2026-03-30b — Page feedback iteration (Steps 1-6) + DialogShell - -**Agent(s):** Claude Opus 4.6 (1M context) - -**Work completed:** -- **IntroStep (Step 1):** Static subheading (removed dynamic text change on selection), ToggleButtonGroup top-left alignment fix -- **ProvidersStep (Step 2):** Heading reduced to h4 "Find a funeral director", SearchBar → location TextField with pin icon, FilterPanel moved below search right-aligned, map fill fix (height:100% → flex:1), hover scrollbar on left panel -- **VenueStep (Step 7):** Same consistency fixes as ProvidersStep (h4, location icon, filter layout, map fill, results count format) -- **PackagesStep (Step 3):** Removed budget filter + "Most Popular" badge + mobile Continue button. Added grouped packages pattern ("Matching your preferences" / "Other packages from [Provider]" with brand accent bars). `onArrange` replaces `onContinue`. Clickable provider card (`onProviderClick`). Heading to h4. -- **DateTimeStep (Step 6):** display3 heading (centered-form consistency). Name fields swapped from MUI TextField to Input atom (external label, no clipping). Multiple preferred dates (up to 3, progressive disclosure). Removed service tradition/religion field. Dividers between question sections. -- **DialogShell atom:** New shared dialog container (header + optional back + close, scrollable body, optional footer). Audited 17→19/20, P1s fixed (focus management, sx pattern). -- **FilterPanel refactored:** Popover → DialogShell (centered Dialog with backdrop) -- **ArrangementDialog refactored:** Now composes DialogShell for consistent chrome -- **PreviewStep + AuthGateStep removed:** Consolidated into ArrangementDialog (D-E) -- **WizardLayout:** ListMapLayout left panel gets thin scrollbar visible on hover - -**Decisions made:** -- Heading convention: display3 for centered-form pages, h4 for narrow panels (list-map, list-detail) -- DialogShell is the standard popup container — all site dialogs compose it -- Service tradition removed from DateTimeStep — flows from provider/package selection, confirmed on summary -- "Service tradition" is the preferred terminology (not "religion" or "religious style") -- Package grouping pattern: matched vs other, with brand accent bar section labels -- FilterPanel uses Dialog (not Popover) for filter controls - -**Open questions:** -- Provider profile popup contents — user will provide details later -- Heading convention (display3 vs h4) should be documented as a decision - -**Next steps:** -- **Resume page feedback from VenueStep (Step 7) onwards** — Steps 1-6 are done -- Remaining pages to review: VenueStep, CrematoriumStep, CemeteryStep, CoffinsStep, CoffinDetailsStep, AdditionalServicesStep, SummaryStep, PaymentStep, ConfirmationStep -- Homepage layout work (user priority — separate task) -- Input atom clipping: audit remaining pages for MUI TextField → Input atom swap where labels clip - ---- - -### Session 2026-03-30a — Tooling upgrades + workflow evaluation - -**Agent(s):** Claude Opus 4.6 (1M context) - -**Work completed:** -- **Storybook addons:** Added `@storybook/addon-storysource` (story source code panel) and `@storybook/addon-a11y` (real-time axe-core accessibility checks) -- **Playwright MCP:** Installed `@playwright/mcp` and registered as MCP server. Enables Claude Code to take screenshots of Storybook for visual verification. Available from next session. -- **Workflow evaluation:** Comprehensive analysis of current capabilities, identified core gap (Claude Code cannot see visual output), researched solutions -- **Antigravity research:** Investigated Google Antigravity IDE for visual polish workflow. Installed on system. Created `GEMINI.md` project rules file. User decided to pause on Antigravity for now and continue with Claude Code + Playwright MCP approach. -- **GEMINI.md:** Created project rules file for Antigravity IDE, mirroring key conventions from CLAUDE.md (token access, atomic tiers, no hardcoded values) - -**Decisions made:** -- Playwright MCP is the primary solution for visual verification gap — enables Claude Code to screenshot Storybook stories and self-correct visual issues -- Antigravity available as secondary tool for visual tweaks but not primary workflow -- Claude Code remains the primary tool for architectural/structural work due to custom skills, memory system, and accumulated project context - -**Open questions:** -- User has refinement feedback from previous session that was partially overlooked — to be addressed next session -- Some items from the user's original feedback across 15 steps were missed when compressed into D-A through D-H decisions - -**Next steps:** -- Restart session to activate Playwright MCP -- User to provide refinement feedback -- Use Playwright MCP to visually verify changes as they're made -- Address remaining P1s from previous session (radiogroup keyboard nav, dialog mobile fullscreen) - ---- - -### Session 2026-03-29e — Feedback iteration Batches 1 & 2 - -**Agent(s):** Claude Opus 4.6 (1M context) - -**Work completed:** -- **Batch 1: Atom + Template Foundation** - - ToggleButtonGroup: label-to-options spacing `mb: 1→2`, top-align content `flex-start`, fixed selected border CSS specificity (added `&.Mui-selected` in grouped selector) - - Heading standardisation: all 6 split-layout steps changed from `h4` → `display3` (ProvidersStep, PackagesStep, PreviewStep, VenueStep, CoffinsStep, CoffinDetailsStep) per D-A - - DateTimeStep: normalised section gaps (scheduling fieldset `mb: 3→4`) - - CrematoriumStep: added subheading for consistency, normalised witness section `mb: 3→4` - - PackagesStep + DateTimeStep: fixed input label clipping (`pt: 0.5` on TextField containers) -- **Batch 2: List-Map Layout Rework (D-B)** - - WizardLayout ListMapLayout: 420px fixed left column, `flex: 1` right panel - - Back link rendered inside left panel (not above split) — eliminates gap above map - - LAYOUT_MAP type updated to accept `backLink` prop for list-map variant - - ProvidersStep + VenueStep: sticky header (heading + search + filters pinned at top of scrollable left panel) -- **Batch 3: FilterPanel molecule + integration (D-C, D-F)** - - New FilterPanel molecule: Popover trigger with active count badge, Clear all, Done actions - - ProvidersStep: inline chips → FilterPanel Popover alongside search bar - - VenueStep: same pattern, filter chips in Popover - - CoffinsStep (D-F): grid-sidebar → wide-form (full-width 4-col grid), filters in Popover - - WizardLayout: added `wide-form` variant (maxWidth lg, single column) for card grids - - FilterPanel stories: Default, WithActiveFilters, SelectFilters, CustomLabel -- **Batch 4: Step Simplifications (D-D, D-G)** - - ProvidersStep (D-D): removed selection state, Continue button, radiogroup pattern. Clicking a provider card triggers navigation directly. Stories updated. - - CoffinDetailsStep (D-G): removed all customisation (handles, lining, nameplate, OptionSection, ProductOption/CoffinDetailsStepValues types). Simplified to coffin profile + Continue CTA. Changed from detail-toggles to centered-form layout. Stories simplified. - - Updated CoffinDetailsStep index.ts re-exports -- **Batch 5: ArrangementDialog organism (D-E)** - - New ArrangementDialog organism: MUI Dialog with two internal steps - - Step 1 (preview): ProviderCardCompact, package summary with sections/items/total, "What happens next" checklist - - Step 2 (auth): SSO buttons, email, progressive disclosure for details, verification code, terms - - Parent controls step state + auth form values; dialog has back arrow and close button - - Stories: Default (full flow), AuthStep, AuthDetails, PrePlanning - - PreviewStep + AuthGateStep kept for now, to be deprecated once dialog is wired in - -**Decisions made:** -- All 8 iteration decisions now implemented: D-A through D-H - -**Quality passes:** -- Ran 3 parallel audits (FilterPanel, ArrangementDialog, all reworked steps) -- FilterPanel: 4 P0 + 2 P1 fixed (forwardRef, useId, aria-controls, dialog role, label prop, scroll) -- ArrangementDialog: 3 P0 + 2 P1 fixed (forwardRef, focus management, aria-live, semantic tokens, Link atom) -- Sticky headers: responsive padding match + top breathing room (pt: 2) -- ProvidersStep: role="list", semantic map token -- VenueStep: aria-label on search, semantic map token -- CoffinDetailsStep: form wrapper added - -**Remaining P1/P2 (for next session):** -- VenueStep/CoffinsStep radiogroup arrow-key navigation (P1) -- ArrangementDialog step number badge hardcoded font size/weight (P1) -- ArrangementDialog mobile fullscreen treatment (P1) -- CoffinDetailsStep centered-form width may be tight for coffin images (P2) -- CTA alignment inconsistency VenueStep vs CoffinsStep/CoffinDetailsStep (P2) -- ArrangementDialog missing story variants: verify, loading, errors, overflow (P2) - -**Open questions:** -- PreviewStep + AuthGateStep: deprecate/remove once ArrangementDialog fully replaces them in the flow -- User to review all steps in Storybook and report any visual issues still present - -**Next steps:** -- User review in Storybook — note any remaining visual issues -- Fix remaining P1s (radiogroup keyboard nav, dialog mobile fullscreen) -- Wire ArrangementDialog into PackagesStep flow -- Component registry updates for FilterPanel + ArrangementDialog - ---- - -### Session 2026-03-29c — Grooming pass: critique/harden/polish all 15 steps - -**Agent(s):** Claude Opus 4.6 (1M context) - -**Work completed:** -- **Full grooming pass across all 15 wizard steps** — applied critique (UX design review), harden (edge cases/error states), and polish (visual alignment/copy/code) frameworks. -- **[P0] CrematoriumStep bug fix:** `