Polish ComparisonPage mobile cards + page layout
- ComparisonTabCard: width 210 → 235; recommended badge switched to filled brand + StarRoundedIcon matching the desktop ComparisonColumnCard treatment; removed glow + active glow shadow in favour of the standard shadow-sm; border colour brand-500 → brand-600; pt 2.4 → 3.5. - ComparisonPackageCard: verified badge replaced with inline VerifiedOutlinedIcon to the left of the provider name (matches desktop pattern); warm tint confined to the header (Card body now explicitly white); 2px brand-600 border when recommended; header padding px 2.5 → 3, pt 2.5 → 3, pb 2 → 4; spacing pass across the provider identity / package info / sections groups — Divider my 1.5 → 3, section mb 3 → 5, item py 1.5 → 2, heading→first-item 1.5 → 2.5. - ComparisonPage mobile: Divider between page header and tab rail; "Choose a package to view" h2 heading (user-centric copy), used as aria-labelledby for the tablist; dot indicator below the rail (8px grey, active 24×8 brand-600 pill) — aria-hidden and tabIndex=-1 so the tab rail above remains the canonical accessible navigation. Also leaves the Figma capture script in preview-head.html for future page captures. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
<script src="https://mcp.figma.com/mcp/html-to-design/capture.js" async></script>
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||
<link
|
||||
|
||||
@@ -54,9 +54,9 @@ duplicates) and MUST update it after completing one.
|
||||
| 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). |
|
||||
| ComparisonPackageCard | done | Card + Button + Divider + Typography + Tooltip + LocationOnOutlinedIcon + VerifiedOutlinedIcon + StarRoundedIcon + CheckCircleOutlineIcon + InfoOutlinedIcon | Mobile full-width package card for ComparisonPage tabpanels. Provider header (inline VerifiedOutlinedIcon left of name when verified, name, location + rating, divider, package name, price block, full-width CTA) + itemised sections with left-accent headings. **Warm tint confined to header only** (not Card body) — Card is white (`background.paper`), header has `surface-warm` (recommended) or `surface-subtle` (verified) bg. **2px brand-600 border** when recommended (matches desktop ComparisonColumnCard). Header `px: 3, pt: 3, pb: 4`. Package-info subgroup (name/label/price) in tight nested flex columns. Generous section spacing (`mb: 5` between sections, `py: 2` per item). Recommended banner at top. Shadow (shadow-sm). Medium full-width button. Reuses `ComparisonPackage` type from ComparisonTable. Shared by ComparisonPage V2 and V1 (extracted 2026-04-09). |
|
||||
| ComparisonColumnCard | done | Card + Badge + Button + Divider + Typography + Tooltip + Link + StarRoundedIcon + VerifiedOutlinedIcon | Desktop column header card for ComparisonTable. Floating badge: **medium** (26px) filled brand + StarRoundedIcon for recommended; soft brand + VerifiedOutlinedIcon for verified. Provider name **wraps to 2 lines** (`WebkitLineClamp: 2`) in a reserved 36px minHeight slot bottom-aligned so 1-line names anchor with location/rating/price at a consistent baseline. Recommended card: 2px brand-600 border + warm `selected` Card state + inline VerifiedOutlinedIcon left of name. `pt: 5` (40px breathing above name), uniform regardless of verified/recommended. Remove link always renders as the same Link element (visibility-hidden when not applicable) so CTA+footer align across all cards. Per-column wrapper in ComparisonTable is `display: flex` with `flex: 1` passed to the card root so all cards stretch to row height. Extracted from ComparisonTable (2026-04-12). |
|
||||
| ComparisonTabCard | done | Card + Badge + Typography + StarRoundedIcon | Mobile tab rail card for ComparisonPage. Provider name + package name + price. Recommended badge in normal flow with negative margin overlap — **filled brand + StarRoundedIcon** (matches desktop ComparisonColumnCard treatment, size="small" at 14px icon). **Fixed 235px width** (was 210). Border `brand-600` when recommended (consistent with primary). No glow — uses standard `shadow-sm` like other cards. `pt: 3.5` inside card. Shared by V1 and V2 (extracted 2026-04-12). |
|
||||
|
||||
## Organisms
|
||||
|
||||
@@ -65,7 +65,7 @@ duplicates) and MUST update it after completing one.
|
||||
| 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. |
|
||||
| ComparisonTable | done | Typography + Card + Tooltip + ComparisonColumnCard | Side-by-side package comparison. **Fixed column widths** (300px row-label + 300px per package, exported as `COMPARISON_TABLE_COL_WIDTH`). Natural width = `300 × (n+1)`. **Sticky-left** on row-label column across every per-section mini-table. **Tiered hover**: base cells → `surface-subtle`, recommended column cells → `surface-warm` (resting 50% opacity, promotes to full on row hover via color-mix). Per-section mini-tables with left-accent brand heading. **"Not Included"** rendering: `unavailable` cell values in `Optionals`/`Extras` sections render "Not Included" (neutral-500 weight 500); `Essentials` keeps em-dash. `CellIconText` local helper applies `lineHeight: 1` to icon+text rows for optical centre alignment. ARIA table roles. Desktop only (mobile in ComparisonPage). Audit: 17/20 (pre-restructure). |
|
||||
| FuneralFinder (V3) | done | Typography + Button + Divider + Select + MenuItem + OutlinedInput + custom StatusCard/SectionLabel | **Production version.** Hero search widget — clean form with status cards. Standard card container (surface.raised, card shadow). "How Can We Help" section: two side-by-side StatusCards (Immediate Need default-selected / Pre-planning) — white bg, neutral border, brand border + warm bg when selected, stack on mobile. "Funeral Type" Select + "Location" OutlinedInput with pin icon — standard outlined fields, no focus ring (per design). Overline section labels (text.secondary). CTA "Find Funeral Directors →" always active — validates on click, scrolls to first missing field. Required: status + location. Funeral type defaults to "show all". Dividers after header and before CTA. WAI-ARIA roving tabindex on radiogroup. aria-labelledby via useId(). Critique: 33/40 (Good). Audit: 18/20 (Excellent). |
|
||||
| FuneralFinder V1 | archived | Typography + Button + Chip + Input + Divider + Link + custom ChoiceCard/TypeCard/CompletedRow/StepHeading | Archived — viewable in Storybook under Archive/. Stepped conversational flow. Audit: 14/20. Critique: 29/40. |
|
||||
| FuneralFinder V2 | archived | Typography + Button + Input + Divider + Select + MenuItem + custom StepCircle | Archived — viewable in Storybook under Archive/. Quick-form with step circles. Audit: 18/20. Critique: 33/40. |
|
||||
@@ -78,7 +78,7 @@ duplicates) and MUST update it after completing one.
|
||||
|
||||
| Component | Status | Composed of | Notes |
|
||||
|-----------|--------|-------------|-------|
|
||||
| WizardLayout | done | Container + Box + Link + Typography + Navigation (slot) + StepIndicator (slot) | Page-level layout for arrangement wizard. 5 variants: centered-form, list-map, list-detail, grid-sidebar, detail-toggles. Nav slot, sticky help bar, optional back link, optional progress stepper + running total. `<main>` landmark wrapper. |
|
||||
| WizardLayout | done | Container + Box + Link + Typography + Navigation (slot) + StepIndicator (slot) | Page-level layout for arrangement wizard. **6 variants**: centered-form, wide-form, list-map, list-detail, grid-sidebar, detail-toggles, **bleed**. `bleed` = viewport-locked + `<main>` as single scroll container (both axes) + no inner Container; back link routed into children; scroll host marked `data-wizard-scroll` so descendants can find it (IntersectionObserver roots, etc.). Used by ComparisonPage. Nav slot, sticky help bar, optional back link, optional progress stepper + running total. `<main>` landmark wrapper. |
|
||||
|
||||
## Pages
|
||||
|
||||
@@ -105,7 +105,7 @@ duplicates) and MUST update it after completing one.
|
||||
| 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 (V2) | done | WizardLayout (**bleed** desktop / wide-form mobile) + ComparisonTable + ComparisonTabCard + ComparisonPackageCard + Divider + Typography + Button + Link | **Production version.** Package comparison page, restructured 2026-04-17. **Desktop**: `bleed` WizardLayout variant. Structure: centred page-header container (maxWidth 1200 = `COMPARISON_TABLE_COL_WIDTH × 4`) with own Back link → `<Divider>` → full-bleed `[spacer][ComparisonTable][spacer]` flex row. When viewport > 1200 spacers centre the table; when a 4th+ package makes the table wider than viewport, spacers collapse to their min-width (16/24px matching the page-header padding) and the table extends rightward with the content's left edge pinned. Recommended package as first (leftmost) column with warm tint + 2px brand-600 border + filled Recommended badge. **Mobile**: `<Divider>` between page header and tab rail. "Choose a package to view" h2 heading (user-centric), serves as `aria-labelledby` for the tablist. Horizontal tab rail (role="tablist") of `ComparisonTabCard` (235px each) + **dot indicator** below (8px grey dots, active expands to 24×8 brand-600 pill, aria-hidden, tabIndex=-1 — visual supplement to the tab rail which is canonical accessible nav). Single `ComparisonPackageCard` in role="tabpanel"; recommended tab is first in rail, first user-selected package is initially active. Share + Print in page header (desktop). Back link, help bar. |
|
||||
| ComparisonPage V1 | archived | WizardLayout + ComparisonTable + Card + Typography + Button + Divider | Archived — viewable in Storybook under Archive/. Recommended package as **last** column/tab. Same component tree as V2. |
|
||||
|
||||
## Future enhancements
|
||||
|
||||
@@ -26,6 +26,139 @@ Each entry follows this structure:
|
||||
|
||||
## Sessions
|
||||
|
||||
### Session 2026-04-17 — ComparisonPage restructure (scroll model, sticky-left, tiered hover) + card refinements + mobile polish
|
||||
|
||||
**Agent(s):** Claude Opus 4.7 (1M context)
|
||||
|
||||
**Work completed:**
|
||||
|
||||
**Phase A — WizardLayout `bleed` variant (new):**
|
||||
- Added a 7th layout variant `bleed` for pages that own their own alignment logic.
|
||||
- Viewport-locked (`height: 100vh; overflow: hidden` on root). `<main>` becomes the single scroll container (both axes) via `flex: 1; overflow: auto`.
|
||||
- No inner `Container` — children render full-bleed.
|
||||
- Back link slot passed into children (like `list-map` / `detail-toggles`) so it scrolls with content.
|
||||
- `data-wizard-scroll` attribute on the scroll host — used by descendants to find the scroll ancestor (e.g. for IntersectionObserver roots).
|
||||
|
||||
**Phase B — ComparisonPage + ComparisonTable restructure:**
|
||||
- `ComparisonPage` (desktop) now uses `bleed`. Structure: centred page-header container (maxWidth = `COMPARISON_TABLE_COL_WIDTH × 4` = 1200px) → `<Divider>` → full-bleed flex row `[spacer][table][spacer]`. Matching horizontal padding (16/24px) between container and spacers keeps content left-edges aligned on all viewports.
|
||||
- Own `<Back>` link inside the page-header container (not `WizardLayout`'s) so it sits under the shared left-edge rather than the raw scroll-host edge.
|
||||
- `ComparisonTable` rewritten with fixed column widths: `COMPARISON_TABLE_COL_WIDTH = 300` exported as a constant. Natural width = `300 × (packages.length + 1)`.
|
||||
- Sticky-left on row-label column across every per-section mini-table. Works because each mini-table shares the scroll ancestor (the bleed `<main>`).
|
||||
- Tiered hover: base row-cells → `surface-subtle` (#fafafa), recommended column cells → `surface-warm` (#fef9f5). Recommended column has a resting 50%-opacity warm tint that promotes to full warm on row hover (via `color-mix`).
|
||||
- Per-section mini-tables kept (user preference) with left-accent brand heading.
|
||||
- "Not Included" rendering: new rule — `unavailable` cell values in sections whose heading matches `OPTIONAL_SECTION_HEADINGS` (currently `Optionals`, `Extras`) render "Not Included" in neutral-500; `Essentials` keeps the em-dash. Meaning: missing in Essentials = "not itemised", missing in Extras = "deliberately absent".
|
||||
- `CellIconText` local helper introduced for icon+label cell values (complimentary, included, unknown). Sets `lineHeight: 1` on flex container AND Typography so geometric and optical centres align — fixes the icons-sitting-slightly-high visual bug.
|
||||
|
||||
**Phase C (stripped):** Built a collapsing sticky mini-header (IntersectionObserver + sentinel + max-height transition) then removed per user request — they want to revisit later. All machinery (observer, state, sentinel, Button import, z-index const) removed clean.
|
||||
|
||||
**ComparisonColumnCard refinements:**
|
||||
- Fixed physical height consistency: outer wrapper in ComparisonTable is now `display: flex; flexDirection: column; minWidth: 0`, and the card root receives `flex: 1` so all cards stretch to the tallest grid-row height.
|
||||
- Top padding inside card bumped from conditional `2.5/3` to uniform `pt: 5` (40px) — significantly more breathing room above the provider name. Bottom padding `pb: 2.5` → `pb: 3`.
|
||||
- Badge size bumped from `small` (22px) to `medium` (26px) with icon fontSize 14 → 16 and `top: -12` → `-13`.
|
||||
- Remove link footer: instead of conditional Link-vs-Box, always renders the same `Link` element; visibility-hidden + tabindex=-1 + aria-hidden when no Remove action applies. CTA + footer row layouts now identical across all cards, fixing a sub-pixel CTA-height drift.
|
||||
- Provider name: wraps to up to 2 lines via `WebkitLineClamp: 2`. Name Box has `minHeight: 36` (= 2 × label-line-height) and `alignItems: flex-end` — 1-line names sit at the bottom of a reserved 2-line slot, so location/rating/price below stay on the same baseline regardless of wrap.
|
||||
- Inline verified icon adjusted from `mt: 3px` + alignItems:center to `mb: 2px` + alignItems:flex-end to pair with bottom-aligned text.
|
||||
- Tooltip threshold for long provider names raised from 24 to 50 chars (wrapping handles most cases).
|
||||
- Internal grouping spacing pass: outer gap `0.5 → 1`, Divider `my: 1 → 1.5`. Price subgroup wrapped in its own sub-Box with `gap: 0.25` so "Total package price" label + amount stay visually joined despite the larger outer gap. Redundant Button `mt: 1.5` and Remove `mt: 0.5` removed.
|
||||
|
||||
**Mobile polish — ComparisonTabCard:**
|
||||
- Width: 210 → 235 (+25px).
|
||||
- Recommended badge aligned with desktop: `filled` variant + `StarRoundedIcon`, keeps `size="small"` per user instruction.
|
||||
- Removed the glow (`0 0 12px rgba(186, 131, 78, 0.3)`) — uses same `var(--fa-shadow-sm)` as other cards. No custom active-recommended glow either.
|
||||
- Border colour: `brand-500` → `brand-600` (consistent with primary).
|
||||
- Top padding inside card: 2.4 → 3.5.
|
||||
|
||||
**Mobile polish — ComparisonPackageCard:**
|
||||
- Badge removed in favour of inline verified icon (consistent with desktop `ComparisonColumnCard` pattern): `VerifiedOutlinedIcon` in brand-600 sits left of provider name in a flex row when `provider.verified` is true.
|
||||
- Warm background confined to the provider header only: removed `selected={pkg.isRecommended}` from the root Card (it was applying `surface-warm` across the whole card). Explicit `bgcolor: 'background.paper'`. Border: explicit `2px solid brand-600` on the Card when recommended (matches desktop ComparisonColumnCard exactly).
|
||||
- Header horizontal padding: `px: 2.5 → px: 3`. Top padding `pt: 2.5 → pt: 3`, bottom `pb: 2 → pb: 4`.
|
||||
- Spacing between groups: badge→name→metadata bumped (mb: 1 → 2, mb: 0.5 → 1.25, mb: 1.5 → 2). Divider `mb: 1.5 → my: 3`. Package-info subgroup wrapped in flex column with `gap: 0.75` between name and price block; inner price block has `gap: 0.25`. Button `mt: 2 → mt: 3`.
|
||||
- Sections area: `py: 2.5 → pt: 3.5, pb: 3`. Between sections `mb: 3 → mb: 5`. Section heading → first item `mb: 1.5 → mb: 2.5`. Item rows `py: 1.5 → py: 2`. Redundant `mt: 1` on subsequent section headings removed (parent spacing now owns the gap).
|
||||
|
||||
**Mobile polish — ComparisonPage:**
|
||||
- Added `<Divider>` between page header (h1 + subhead) and package selector.
|
||||
- Added `<Typography component="h2">Choose a package to view</Typography>` as user-centric heading for the tab rail. Hooked up as the tablist's `aria-labelledby`.
|
||||
- Dot indicator added below the rail: 8×8px grey neutral-300 dots, active dot expands to `24×8px` brand-600 pill (width transition 200ms). Tap-to-navigate. Container is `aria-hidden="true"` with dots having `tabIndex: -1` — purely visual supplement; the tab rail above remains the canonical accessible navigation, avoiding duplicate tabstops for screen reader / keyboard users.
|
||||
- Tab rail `mb: 3 → 1.5` so dots sit close to the rail they describe.
|
||||
|
||||
**Test data update:**
|
||||
- `pkgMackay.provider.name` extended to "Mackay Family Funeral Directors & Cremation Services" (52 chars) — exercises the 2-line provider-name wrap in all four comparison stories.
|
||||
|
||||
**Decisions made:**
|
||||
- **Scroll model A** (single scroll container on main, page header scrolls away) chosen over B (table-internal scroll with page chrome pinned) and C (hybrid). Makes the width-matching left-edge alignment trick work naturally.
|
||||
- **Sticky columns: row-labels only**, not recommended column. Simpler, preserves horizontal space for other packages on medium screens.
|
||||
- **Per-section mini-tables kept** — user preferred visual rhythm over single continuous table.
|
||||
- **Tokens unchanged**: `brand-50` (#fef9f5) and `brand-600` (#b0610f) are exactly what Make's exploration landed on. No token work needed.
|
||||
- **Collapsing sticky header dropped** — user will revisit. Preserve option; removed all machinery cleanly.
|
||||
- **Info-icon tooltip on mobile package card**: accepted as exception. Touch-device tooltip UX isn't ideal but info is supplementary.
|
||||
|
||||
**Open questions:**
|
||||
- None blocking.
|
||||
|
||||
**Next steps:**
|
||||
- Commit today's work (2 commits: Phase A+B desktop restructure, then card refinements + mobile polish).
|
||||
- Optional: `/audit` on refreshed ComparisonPage + ComparisonTable; `/critique` on the mobile and desktop views.
|
||||
- User flagged next focus areas (not started this session): package select page refinements; map pins / map cards (MapCard molecule is still "planned" in the registry).
|
||||
|
||||
---
|
||||
|
||||
### Session 2026-04-16b — ComparisonColumnCard refinements
|
||||
|
||||
**Agent(s):** Claude Opus 4.6 (1M context)
|
||||
|
||||
**Work completed:**
|
||||
- **Recommended banner removed** — was causing CTA misalignment between recommended and non-recommended cards. Replaced with a floating "Recommended" badge (primary fill, star icon) that replaces the "Verified" badge (soft, checkmark) when recommended.
|
||||
- **Card border fix** — selected state was using `brand-500` (via `--fa-card-border-selected` token) which looked inconsistent with the rest of the primary system. Recommended cards now override to `brand-600` to match banner/button primary colour.
|
||||
- **Inline verified icon** — small `VerifiedOutlinedIcon` in brand-600 now sits to the left of the provider name **only on recommended cards** (recommended providers are always verified). Regular verified providers rely on the top badge alone.
|
||||
- **No-rating fallback** — when `provider.rating == null`, renders a single `—` in the rating slot to keep card heights consistent across all columns.
|
||||
- **CTA alignment** — recommended cards now render an invisible `Remove` placeholder (same height) so the primary CTA button aligns with non-recommended cards that do have a Remove link.
|
||||
- **Remove link dropped to caption** — from `body2` (14px) to `caption` (12px) on both real and spacer versions.
|
||||
- **Gap between verified icon and provider name** bumped from 0.5 to 0.75.
|
||||
|
||||
**Decisions made:**
|
||||
- Star (`StarRoundedIcon`) used for Recommended badge icon — reads as "standout" at 14px and differentiates from the Verified checkmark.
|
||||
- Recommended-card border override is local (sx) rather than a new theme token — the inconsistency is between the token (brand-500) and the rest of the system (brand-600); the right long-term fix is probably updating the token itself.
|
||||
|
||||
**Next steps (tomorrow):**
|
||||
- Retry Sheffield remote push on next `/publish` (still 502 last session).
|
||||
- Consider promoting the `brand-500 → brand-600` border fix to the `--fa-card-border-selected` token if it applies broadly.
|
||||
|
||||
---
|
||||
|
||||
### Session 2026-04-16 — HomePage refinements + Navigation dropdown + hero image
|
||||
|
||||
**Agent(s):** Claude Opus 4.6 (1M context)
|
||||
|
||||
**Work completed:**
|
||||
- **Navigation organism extended** — `NavItem.children` now supported. Desktop renders dropdown menu (MUI Menu, click-triggered), mobile renders collapsible section in drawer. Story `Organisms/Navigation > WithDropdown` added.
|
||||
- **Locations nav added** — Melbourne, Brisbane, Sydney, South Coast NSW, Central Coast NSW, placed before FAQ in all four HomePage stories.
|
||||
- **Hero refinements (HomePage)** — new `hero-couple.jpg` background (compressed 1.4MB → 239KB via ImageMagick `-quality 82 -interlace Plane -strip`); italic tagline "Trusted by thousands of families across Australia" above h1; hero text container widened from md (900px) to 990px; mobile top padding increased; mobile side padding on FuneralFinder bumped from 16px to 24px.
|
||||
- **Hero h1 typography** — promoted from `display3` (same as section h2s) to `display2` (52px desktop / 24px mobile) for hierarchy contrast. Still renders as semantic `<h1>`.
|
||||
- **Section overlines added** — "FUNERAL ARRANGER REVIEWS" above "What families are saying"; "WHY USE FUNERAL ARRANGER" above "4 Reasons to use Funeral Arranger" (renamed from "How it works"). Placeholder body copy removed from features section.
|
||||
- **Features block body copy removed** — "Search local funeral directors, compare transparent pricing..." paragraph removed; body now only renders if explicitly passed.
|
||||
- **CTA button promoted** — "Start planning" in the "We Are Here When You Need Us" section changed from text/large to contained/medium.
|
||||
- **Arrow removed** from "Start exploring" text button.
|
||||
- **FuneralFinderV3 header removed** — form now starts directly at "How can we help"; unused `heading`/`subheading` props deleted; consumers updated.
|
||||
- **Mobile typography scaling** — body1 paragraphs under display3 headings now scale to 14px on mobile (better hierarchy vs the 22px mobile display3). Applied to Discover, Why Use FA, and Features sections, plus FAQ questions.
|
||||
- **Why Use FA text block** — centre-aligned on mobile, left-aligned on desktop.
|
||||
- **HomePage captured to Figma** — node 6061-25005 via capture-to-figma skill.
|
||||
|
||||
**Publishing:**
|
||||
- Builds 6–9 published to Chromatic across the session. Build 9 is current client-facing: https://69c9f45d915025e56139051e-ktlogciofe.chromatic.com/
|
||||
- Asset sync step added to `/publish` skill — new `hero-couple.jpg` picked up automatically.
|
||||
- Sheffield remote returning 502 intermittently (server-side) — skipped, retry on next publish.
|
||||
|
||||
**Decisions made:**
|
||||
- `body1` under `display3` gets a mobile fontSize override (14px) rather than adding a new theme variant — the issue is contextual, not systemic.
|
||||
- Nav dropdown trigger is a plain button (no chevron) per user preference; mobile keeps expand/collapse chevrons because they're tappable affordances.
|
||||
- Hero image filename convention: short + content-descriptive (`hero-couple.jpg`), not marketing-suffixed.
|
||||
|
||||
**Next steps:**
|
||||
- Retry Sheffield push on next `/publish`.
|
||||
- Consider extracting the inline FAQ accordion in HomePage to a shared molecule if used on more pages.
|
||||
|
||||
---
|
||||
|
||||
### Session 2026-04-13 — Chromatic image hosting + Gitea domain migration
|
||||
|
||||
**Agent(s):** Claude Opus 4.6 (1M context)
|
||||
|
||||
@@ -9,7 +9,6 @@ import VerifiedOutlinedIcon from '@mui/icons-material/VerifiedOutlined';
|
||||
import type { SxProps, Theme } from '@mui/material/styles';
|
||||
import { Typography } from '../../atoms/Typography';
|
||||
import { Button } from '../../atoms/Button';
|
||||
import { Badge } from '../../atoms/Badge';
|
||||
import { Divider } from '../../atoms/Divider';
|
||||
import { Card } from '../../atoms/Card';
|
||||
import type { ComparisonPackage, ComparisonCellValue } from '../../organisms/ComparisonTable';
|
||||
@@ -125,12 +124,21 @@ export const ComparisonPackageCard = React.forwardRef<HTMLDivElement, Comparison
|
||||
<Card
|
||||
ref={ref}
|
||||
variant="outlined"
|
||||
selected={pkg.isRecommended}
|
||||
padding="none"
|
||||
sx={[
|
||||
{
|
||||
overflow: 'hidden',
|
||||
boxShadow: 'var(--fa-shadow-sm)',
|
||||
// Body defaults to white; only the header carries the warm/subtle
|
||||
// tint so the tint signals "provider" rather than washing the
|
||||
// whole card.
|
||||
bgcolor: 'background.paper',
|
||||
// Match the desktop ComparisonColumnCard recommended treatment:
|
||||
// explicit 2px brand-600 border (same as Card's selected state,
|
||||
// but without the warm background wash that `selected` applies).
|
||||
...(pkg.isRecommended && {
|
||||
border: '2px solid var(--fa-color-brand-600)',
|
||||
}),
|
||||
},
|
||||
...(Array.isArray(sx) ? sx : [sx]),
|
||||
]}
|
||||
@@ -158,31 +166,38 @@ export const ComparisonPackageCard = React.forwardRef<HTMLDivElement, Comparison
|
||||
bgcolor: pkg.isRecommended
|
||||
? 'var(--fa-color-surface-warm)'
|
||||
: 'var(--fa-color-surface-subtle)',
|
||||
px: 2.5,
|
||||
pt: 2.5,
|
||||
pb: 2,
|
||||
px: 3,
|
||||
pt: 3,
|
||||
pb: 4,
|
||||
}}
|
||||
>
|
||||
{/* Verified badge */}
|
||||
{pkg.provider.verified && (
|
||||
<Badge
|
||||
color="brand"
|
||||
variant="soft"
|
||||
size="small"
|
||||
icon={<VerifiedOutlinedIcon sx={{ fontSize: 14 }} />}
|
||||
sx={{ mb: 1 }}
|
||||
>
|
||||
Verified
|
||||
</Badge>
|
||||
)}
|
||||
|
||||
{/* Provider name */}
|
||||
<Typography variant="label" sx={{ fontWeight: 600, display: 'block', mb: 0.5 }}>
|
||||
{pkg.provider.name}
|
||||
</Typography>
|
||||
{/* Provider name with optional inline verified icon (matches desktop
|
||||
ComparisonColumnCard treatment) */}
|
||||
<Box
|
||||
sx={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
gap: 0.75,
|
||||
mb: 1.25,
|
||||
}}
|
||||
>
|
||||
{pkg.provider.verified && (
|
||||
<VerifiedOutlinedIcon
|
||||
sx={{
|
||||
fontSize: 16,
|
||||
color: 'var(--fa-color-brand-600)',
|
||||
flexShrink: 0,
|
||||
}}
|
||||
aria-label="Verified provider"
|
||||
/>
|
||||
)}
|
||||
<Typography variant="label" sx={{ fontWeight: 600 }}>
|
||||
{pkg.provider.name}
|
||||
</Typography>
|
||||
</Box>
|
||||
|
||||
{/* Location + Rating */}
|
||||
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1, mb: 1.5 }}>
|
||||
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1, mb: 2 }}>
|
||||
<Box sx={{ display: 'flex', alignItems: 'center', gap: 0.25 }}>
|
||||
<LocationOnOutlinedIcon sx={{ fontSize: 14, color: 'text.secondary' }} aria-hidden />
|
||||
<Typography variant="caption" color="text.secondary">
|
||||
@@ -203,18 +218,22 @@ export const ComparisonPackageCard = React.forwardRef<HTMLDivElement, Comparison
|
||||
)}
|
||||
</Box>
|
||||
|
||||
<Divider sx={{ mb: 1.5 }} />
|
||||
<Divider sx={{ my: 3 }} />
|
||||
|
||||
{/* Package name + price */}
|
||||
<Typography variant="h5" component="p">
|
||||
{pkg.name}
|
||||
</Typography>
|
||||
<Typography variant="caption" color="text.secondary">
|
||||
Total package price
|
||||
</Typography>
|
||||
<Typography variant="h3" sx={{ color: 'primary.main', fontWeight: 700 }}>
|
||||
{formatPrice(pkg.price)}
|
||||
</Typography>
|
||||
{/* Package info group — name, label, price stacked with small internal gap */}
|
||||
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 0.75 }}>
|
||||
<Typography variant="h5" component="p">
|
||||
{pkg.name}
|
||||
</Typography>
|
||||
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 0.25 }}>
|
||||
<Typography variant="caption" color="text.secondary">
|
||||
Total package price
|
||||
</Typography>
|
||||
<Typography variant="h3" sx={{ color: 'primary.main', fontWeight: 700 }}>
|
||||
{formatPrice(pkg.price)}
|
||||
</Typography>
|
||||
</Box>
|
||||
</Box>
|
||||
|
||||
<Button
|
||||
variant={pkg.provider.verified ? 'contained' : 'soft'}
|
||||
@@ -222,14 +241,14 @@ export const ComparisonPackageCard = React.forwardRef<HTMLDivElement, Comparison
|
||||
size="medium"
|
||||
fullWidth
|
||||
onClick={() => onArrange(pkg.id)}
|
||||
sx={{ mt: 2 }}
|
||||
sx={{ mt: 3 }}
|
||||
>
|
||||
{pkg.provider.verified ? 'Make Arrangement' : 'Make Enquiry'}
|
||||
</Button>
|
||||
</Box>
|
||||
|
||||
{/* Sections — with left accent borders on headings */}
|
||||
<Box sx={{ px: 2.5, py: 2.5 }}>
|
||||
<Box sx={{ px: 2.5, pt: 3.5, pb: 3 }}>
|
||||
{pkg.itemizedAvailable === false ? (
|
||||
<Box sx={{ textAlign: 'center', py: 3 }}>
|
||||
<Typography variant="body2" color="text.secondary" sx={{ fontStyle: 'italic' }}>
|
||||
@@ -238,15 +257,14 @@ export const ComparisonPackageCard = React.forwardRef<HTMLDivElement, Comparison
|
||||
</Box>
|
||||
) : (
|
||||
pkg.sections.map((section, sIdx) => (
|
||||
<Box key={section.heading} sx={{ mb: sIdx < pkg.sections.length - 1 ? 3 : 0 }}>
|
||||
<Box key={section.heading} sx={{ mb: sIdx < pkg.sections.length - 1 ? 5 : 0 }}>
|
||||
{/* Section heading with left accent */}
|
||||
<Box
|
||||
sx={{
|
||||
borderLeft: '3px solid',
|
||||
borderLeftColor: 'var(--fa-color-brand-500)',
|
||||
pl: 1.5,
|
||||
mb: 1.5,
|
||||
mt: sIdx > 0 ? 1 : 0,
|
||||
mb: 2.5,
|
||||
}}
|
||||
>
|
||||
<Typography variant="h6" component="h3">
|
||||
@@ -262,7 +280,7 @@ export const ComparisonPackageCard = React.forwardRef<HTMLDivElement, Comparison
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
gap: 2,
|
||||
py: 1.5,
|
||||
py: 2,
|
||||
borderBottom: '1px solid',
|
||||
borderColor: 'divider',
|
||||
}}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import React from 'react';
|
||||
import Box from '@mui/material/Box';
|
||||
import StarRoundedIcon from '@mui/icons-material/StarRounded';
|
||||
import type { SxProps, Theme } from '@mui/material/styles';
|
||||
import { Typography } from '../../atoms/Typography';
|
||||
import { Badge } from '../../atoms/Badge';
|
||||
@@ -58,12 +59,15 @@ export const ComparisonTabCard = React.forwardRef<HTMLDivElement, ComparisonTabC
|
||||
...(Array.isArray(sx) ? sx : [sx]),
|
||||
]}
|
||||
>
|
||||
{/* Recommended badge in normal flow — overlaps card via negative mb */}
|
||||
{/* Recommended badge in normal flow — overlaps card via negative mb.
|
||||
Matches the desktop ComparisonColumnCard styling (filled brand +
|
||||
star icon) for consistency between surfaces. */}
|
||||
{pkg.isRecommended ? (
|
||||
<Badge
|
||||
color="brand"
|
||||
variant="soft"
|
||||
variant="filled"
|
||||
size="small"
|
||||
icon={<StarRoundedIcon sx={{ fontSize: 14 }} />}
|
||||
sx={{
|
||||
mb: '-10px',
|
||||
zIndex: 1,
|
||||
@@ -89,21 +93,18 @@ export const ComparisonTabCard = React.forwardRef<HTMLDivElement, ComparisonTabC
|
||||
onClick={onClick}
|
||||
interactive
|
||||
sx={{
|
||||
width: 210,
|
||||
width: 235,
|
||||
cursor: 'pointer',
|
||||
boxShadow: 'var(--fa-shadow-sm)',
|
||||
...(pkg.isRecommended && {
|
||||
borderColor: 'var(--fa-color-brand-500)',
|
||||
boxShadow: '0 0 12px rgba(186, 131, 78, 0.3)',
|
||||
borderColor: 'var(--fa-color-brand-600)',
|
||||
}),
|
||||
...(isActive && {
|
||||
boxShadow: pkg.isRecommended
|
||||
? '0 0 14px rgba(186, 131, 78, 0.4)'
|
||||
: 'var(--fa-shadow-md)',
|
||||
boxShadow: 'var(--fa-shadow-md)',
|
||||
}),
|
||||
}}
|
||||
>
|
||||
<Box sx={{ px: 2, pt: 2.4, pb: 2 }}>
|
||||
<Box sx={{ px: 2, pt: 3.5, pb: 2 }}>
|
||||
<Typography
|
||||
variant="labelSm"
|
||||
sx={{
|
||||
|
||||
Reference in New Issue
Block a user