Refine PackageDetail header + section hierarchy from review

PackageDetail:
- Warm header band (surface.warm) with "Package" overline, h3 name,
  h5 price in brand colour — creates distinct decision zone
- Section headings bumped to h6 (16px/600) — clear hierarchy vs
  LineItem body2 (14px/500)
- Divider + subtext before Extras: "These items can be added to your
  package at additional cost"
- Top padding increased, content padding increased (py: 3)
- Remove redundant textTransform/letterSpacing on overline (P2 fix)

LineItem:
- Item gap increased in PackageContents story (12px → 16px)

Audit: 19/20 (Excellent). 0 P0, 0 P1.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-26 08:49:01 +11:00
parent 0ed0adc835
commit ab1134eac0

View File

@@ -57,12 +57,17 @@ export interface PackageDetailProps {
// ─── Helpers ───────────────────────────────────────────────────────────────── // ─── Helpers ─────────────────────────────────────────────────────────────────
/** Renders a section heading + list of LineItems */ /** Renders a section heading + list of LineItems */
function SectionBlock({ section }: { section: PackageSection }) { function SectionBlock({ section, subtext }: { section: PackageSection; subtext?: string }) {
return ( return (
<Box> <Box>
<Typography variant="label" component="h3" sx={{ display: 'block', mb: 2 }}> <Typography variant="h6" component="h3" sx={{ mb: subtext ? 0.5 : 2 }}>
{section.heading} {section.heading}
</Typography> </Typography>
{subtext && (
<Typography variant="caption" color="text.secondary" sx={{ display: 'block', mb: 2 }}>
{subtext}
</Typography>
)}
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 2 }}> <Box sx={{ display: 'flex', flexDirection: 'column', gap: 2 }}>
{section.items.map((item) => ( {section.items.map((item) => (
<LineItem <LineItem
@@ -87,13 +92,12 @@ function SectionBlock({ section }: { section: PackageSection }) {
* grouped line items, total, optional extras, and T&Cs. * grouped line items, total, optional extras, and T&Cs.
* *
* Structure: * Structure:
* - **Header** (warm bg): Package name, price, and CTA buttons
* - **sections** (before total): What's included in the package price * - **sections** (before total): What's included in the package price
* (Essentials, Complimentary Items) * (Essentials, Complimentary Items)
* - **total**: The package price * - **total**: The package price
* - **extras** (after total): Additional items that can be added at extra cost * - **extras** (after total): Additional items that can be added at extra cost
* * - **terms**: Provider T&Cs (grey footer)
* Used as the right-side panel on the Package Select page. The contents and
* T&Cs are provider-authored and must be displayed in full.
* *
* "Make Arrangement" is the FA term for selecting/committing to a package. * "Make Arrangement" is the FA term for selecting/committing to a package.
* *
@@ -129,20 +133,37 @@ export const PackageDetail = React.forwardRef<HTMLDivElement, PackageDetailProps
...(Array.isArray(sx) ? sx : [sx]), ...(Array.isArray(sx) ? sx : [sx]),
]} ]}
> >
{/* Main content area */} {/* Header band — warm bg to separate from content */}
<Box sx={{ px: { xs: 2, sm: 3 }, py: 2 }}> <Box
{/* Header: name + price */} sx={{
<Box sx={{ mb: 2 }}> bgcolor: 'var(--fa-color-surface-warm)',
<Typography variant="h4" component="h2"> px: { xs: 2, sm: 3 },
{name} pt: 3,
</Typography> pb: 2.5,
<Typography variant="h6" color="text.secondary" sx={{ mt: 0.5 }}> }}
${price.toLocaleString('en-AU')} >
</Typography> <Typography
</Box> variant="overlineSm"
sx={{
color: 'text.secondary',
display: 'block',
mb: 1,
}}
>
Package
</Typography>
<Typography variant="h3" component="h2">
{name}
</Typography>
<Typography
variant="h5"
sx={{ mt: 0.5, color: 'primary.main', fontWeight: 600 }}
>
${price.toLocaleString('en-AU')}
</Typography>
{/* CTA buttons */} {/* CTA buttons */}
<Box sx={{ display: 'flex', flexDirection: { xs: 'column', sm: 'row' }, gap: 1.5, mb: 3 }}> <Box sx={{ display: 'flex', flexDirection: { xs: 'column', sm: 'row' }, gap: 1.5, mt: 2.5 }}>
<Button <Button
variant="contained" variant="contained"
size="large" size="large"
@@ -165,9 +186,10 @@ export const PackageDetail = React.forwardRef<HTMLDivElement, PackageDetailProps
</Button> </Button>
)} )}
</Box> </Box>
</Box>
<Divider sx={{ mb: 3 }} /> {/* Package contents */}
<Box sx={{ px: { xs: 2, sm: 3 }, py: 3 }}>
{/* Main sections — included in the package price */} {/* Main sections — included in the package price */}
{sections.map((section, idx) => ( {sections.map((section, idx) => (
<Box key={section.heading} sx={{ mb: idx < sections.length - 1 ? 3 : 0 }}> <Box key={section.heading} sx={{ mb: idx < sections.length - 1 ? 3 : 0 }}>
@@ -182,9 +204,13 @@ export const PackageDetail = React.forwardRef<HTMLDivElement, PackageDetailProps
{/* Extras — additional cost items after the total */} {/* Extras — additional cost items after the total */}
{extras && extras.items.length > 0 && ( {extras && extras.items.length > 0 && (
<Box sx={{ mt: 3 }}> <>
<SectionBlock section={extras} /> <Divider sx={{ my: 3 }} />
</Box> <SectionBlock
section={extras}
subtext="These items can be added to your package at additional cost."
/>
</>
)} )}
</Box> </Box>