format: Apply Prettier to existing codebase

Formatting-only changes across all component and story files.
No logic or behaviour changes — only whitespace, line breaks, and trailing commas.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-27 16:42:16 +11:00
parent aa7cdeecf0
commit 047d913960
46 changed files with 1510 additions and 886 deletions

View File

@@ -15,12 +15,7 @@ const FALogoInverse = () => (
);
const FALogoNav = () => (
<Box
component="img"
src="/brandlogo/logo-full.svg"
alt="Funeral Arranger"
sx={{ height: 28 }}
/>
<Box component="img" src="/brandlogo/logo-full.svg" alt="Funeral Arranger" sx={{ height: 28 }} />
);
const defaultLinkGroups = [
@@ -169,8 +164,8 @@ export const FullPage: Story = {
Find a funeral director
</Typography>
<Typography variant="body1" color="text.secondary" sx={{ mb: 4, maxWidth: 600 }}>
Compare trusted funeral directors in your area. View services,
pricing, and reviews to find the right support for your family.
Compare trusted funeral directors in your area. View services, pricing, and reviews to
find the right support for your family.
</Typography>
{Array.from({ length: 4 }).map((_, i) => (
<Box

View File

@@ -64,19 +64,7 @@ export interface FooterProps {
* ```
*/
export const Footer = React.forwardRef<HTMLDivElement, FooterProps>(
(
{
logo,
tagline,
linkGroups = [],
phone,
email,
copyright,
legalLinks = [],
sx,
},
ref,
) => {
({ logo, tagline, linkGroups = [], phone, email, copyright, legalLinks = [], sx }, ref) => {
const year = new Date().getFullYear();
const copyrightText = copyright || `\u00A9 ${year} Funeral Arranger. All rights reserved.`;
@@ -143,10 +131,7 @@ export const Footer = React.forwardRef<HTMLDivElement, FooterProps>(
<Typography variant="overlineSm" sx={overlineSx}>
Email
</Typography>
<Link
href={`mailto:${email}`}
sx={contactLinkSx}
>
<Link href={`mailto:${email}`} sx={contactLinkSx}>
{email}
</Link>
</Box>
@@ -157,7 +142,15 @@ export const Footer = React.forwardRef<HTMLDivElement, FooterProps>(
{/* Link group columns */}
{linkGroups.map((group) => (
<Grid item xs={6} sm={4} md key={group.heading} component="nav" aria-label={group.heading}>
<Grid
item
xs={6}
sm={4}
md
key={group.heading}
component="nav"
aria-label={group.heading}
>
<Typography
variant="label"
sx={{
@@ -170,7 +163,14 @@ export const Footer = React.forwardRef<HTMLDivElement, FooterProps>(
</Typography>
<Box
component="ul"
sx={{ listStyle: 'none', p: 0, m: 0, display: 'flex', flexDirection: 'column', gap: 1.5 }}
sx={{
listStyle: 'none',
p: 0,
m: 0,
display: 'flex',
flexDirection: 'column',
gap: 1.5,
}}
>
{group.links.map((link) => (
<li key={link.label}>
@@ -206,10 +206,7 @@ export const Footer = React.forwardRef<HTMLDivElement, FooterProps>(
py: 3,
}}
>
<Typography
variant="captionSm"
sx={{ color: 'var(--fa-color-brand-400)' }}
>
<Typography variant="captionSm" sx={{ color: 'var(--fa-color-brand-400)' }}>
{copyrightText}
</Typography>

View File

@@ -9,7 +9,12 @@ import { Typography } from '../../atoms/Typography';
const funeralTypes = [
{ id: 'cremation', label: 'Cremation', hasServiceOption: true },
{ id: 'burial', label: 'Burial', hasServiceOption: true },
{ id: 'water-burial', label: 'Water Burial', note: 'Available in QLD only', hasServiceOption: false },
{
id: 'water-burial',
label: 'Water Burial',
note: 'Available in QLD only',
hasServiceOption: false,
},
];
const themeOptions = [
@@ -152,8 +157,8 @@ export const InHeroDesktop: Story = {
color="text.secondary"
sx={{ textAlign: 'center', mb: 4, maxWidth: 440, mx: 'auto' }}
>
Whether you're thinking ahead or arranging for a loved one, find
trusted local providers with transparent pricing.
Whether you're thinking ahead or arranging for a loved one, find trusted local
providers with transparent pricing.
</Typography>
<FuneralFinder
funeralTypes={funeralTypes}
@@ -199,7 +204,11 @@ export const InHeroMobile: Story = {
]}
/>
<Box sx={{ bgcolor: 'var(--fa-color-brand-100)', px: 3, py: 4, textAlign: 'center' }}>
<Typography variant="h3" component="h1" sx={{ mb: 1.5, color: 'var(--fa-color-brand-950)' }}>
<Typography
variant="h3"
component="h1"
sx={{ mb: 1.5, color: 'var(--fa-color-brand-950)' }}
>
Discover, Explore, and Plan Funerals in Minutes
</Typography>
<Typography variant="body2" color="text.secondary">
@@ -210,7 +219,8 @@ export const InHeroMobile: Story = {
sx={{
height: 180,
bgcolor: 'var(--fa-color-brand-200)',
backgroundImage: 'url(https://images.unsplash.com/photo-1516733968668-dbdce39c0571?w=800&h=400&fit=crop)',
backgroundImage:
'url(https://images.unsplash.com/photo-1516733968668-dbdce39c0571?w=800&h=400&fit=crop)',
backgroundSize: 'cover',
backgroundPosition: 'center',
}}

View File

@@ -146,7 +146,11 @@ function ChoiceCard({
</Typography>
</Box>
{description && (
<Typography variant="caption" component="span" sx={{ display: 'block', mt: 0.5, color: 'text.secondary' }}>
<Typography
variant="caption"
component="span"
sx={{ display: 'block', mt: 0.5, color: 'text.secondary' }}
>
{description}
</Typography>
)}
@@ -214,12 +218,20 @@ function TypeCard({
</Typography>
</Box>
{description && (
<Typography variant="caption" component="span" sx={{ display: 'block', mt: 0.25, color: 'text.secondary' }}>
<Typography
variant="caption"
component="span"
sx={{ display: 'block', mt: 0.25, color: 'text.secondary' }}
>
{description}
</Typography>
)}
{note && (
<Typography variant="captionSm" component="span" sx={{ display: 'block', mt: 0.5, color: 'text.secondary', fontWeight: 500 }}>
<Typography
variant="captionSm"
component="span"
sx={{ display: 'block', mt: 0.5, color: 'text.secondary', fontWeight: 500 }}
>
{note}
</Typography>
)}
@@ -261,7 +273,13 @@ function CompletedRow({
onClick={onChangeClick}
underline="hover"
aria-label={`Change ${question.toLowerCase()}`}
sx={{ color: 'text.secondary', ml: 'auto', minHeight: 44, display: 'inline-flex', alignItems: 'center' }}
sx={{
color: 'text.secondary',
ml: 'auto',
minHeight: 44,
display: 'inline-flex',
alignItems: 'center',
}}
>
Change
</Link>
@@ -348,9 +366,11 @@ export const FuneralFinder = React.forwardRef<HTMLDivElement, FuneralFinderProps
const typeSummary = [typeLabel, themeSuffix].filter(Boolean).join(', ');
const serviceLabel =
servicePref === 'with-service' ? 'With a service'
: servicePref === 'without-service' ? 'No service'
: 'Flexible';
servicePref === 'with-service'
? 'With a service'
: servicePref === 'without-service'
? 'No service'
: 'Flexible';
// ─── Handlers ───────────────────────────────────────────────────
const selectIntent = (value: Intent) => {
@@ -409,7 +429,7 @@ export const FuneralFinder = React.forwardRef<HTMLDivElement, FuneralFinderProps
intent,
planningFor: needsPlanningFor ? (planningFor ?? undefined) : undefined,
funeralTypeId: isExploreAll ? null : (typeSelection ?? null),
servicePreference: (showServiceStep && serviceAnswered) ? servicePref : 'either',
servicePreference: showServiceStep && serviceAnswered ? servicePref : 'either',
themes: selectedThemes,
location: location.trim(),
});
@@ -448,16 +468,32 @@ export const FuneralFinder = React.forwardRef<HTMLDivElement, FuneralFinderProps
{/* ── Completed rows ─────────────────────────────────────── */}
<Collapse in={intent !== null && activeStep !== 1} timeout={250}>
<CompletedRow question="I'm here to" answer={intentLabel} onChangeClick={() => revertTo(1)} />
<CompletedRow
question="I'm here to"
answer={intentLabel}
onChangeClick={() => revertTo(1)}
/>
</Collapse>
<Collapse in={needsPlanningFor && planningFor !== null && activeStep !== 2} timeout={250}>
<CompletedRow question="Planning for" answer={planningForLabel} onChangeClick={() => revertTo(2)} />
<CompletedRow
question="Planning for"
answer={planningForLabel}
onChangeClick={() => revertTo(2)}
/>
</Collapse>
<Collapse in={typeSelected && activeStep !== 3} timeout={250}>
<CompletedRow question="Looking for" answer={typeSummary} onChangeClick={() => revertTo(3)} />
<CompletedRow
question="Looking for"
answer={typeSummary}
onChangeClick={() => revertTo(3)}
/>
</Collapse>
<Collapse in={showServiceStep && serviceAnswered && activeStep !== 4} timeout={250}>
<CompletedRow question="Service" answer={serviceLabel} onChangeClick={() => revertTo(4)} />
<CompletedRow
question="Service"
answer={serviceLabel}
onChangeClick={() => revertTo(4)}
/>
</Collapse>
{/* ── Step 1: Intent ─────────────────────────────────────── */}
@@ -467,13 +503,22 @@ export const FuneralFinder = React.forwardRef<HTMLDivElement, FuneralFinderProps
<Typography
variant="caption"
role="alert"
sx={{ color: 'var(--fa-color-brand-600)', textAlign: 'center', display: 'block', mb: 1.5 }}
sx={{
color: 'var(--fa-color-brand-600)',
textAlign: 'center',
display: 'block',
mb: 1.5,
}}
>
Please let us know how we can help
</Typography>
)}
<StepHeading>How can we help you today?</StepHeading>
<Box role="radiogroup" aria-label="How can we help" sx={{ display: 'flex', flexDirection: 'column', gap: 1.5 }}>
<Box
role="radiogroup"
aria-label="How can we help"
sx={{ display: 'flex', flexDirection: 'column', gap: 1.5 }}
>
<ChoiceCard
label="Arrange a funeral now"
description="Someone has passed and I need to make arrangements"
@@ -494,7 +539,11 @@ export const FuneralFinder = React.forwardRef<HTMLDivElement, FuneralFinderProps
<Collapse in={activeStep === 2 && needsPlanningFor} timeout={250}>
<Box sx={{ mt: 3 }}>
<StepHeading>Who are you planning for?</StepHeading>
<Box role="radiogroup" aria-label="Who are you planning for" sx={{ display: 'flex', flexDirection: 'column', gap: 1.5 }}>
<Box
role="radiogroup"
aria-label="Who are you planning for"
sx={{ display: 'flex', flexDirection: 'column', gap: 1.5 }}
>
<ChoiceCard
label="Myself"
description="I want to plan my own funeral in advance"
@@ -515,7 +564,11 @@ export const FuneralFinder = React.forwardRef<HTMLDivElement, FuneralFinderProps
<Collapse in={activeStep === 3} timeout={250}>
<Box sx={{ mt: 3 }}>
<StepHeading>What type of funeral are you considering?</StepHeading>
<Box role="radiogroup" aria-label="Type of funeral" sx={{ display: 'flex', flexDirection: 'column', gap: 1.5 }}>
<Box
role="radiogroup"
aria-label="Type of funeral"
sx={{ display: 'flex', flexDirection: 'column', gap: 1.5 }}
>
{funeralTypes.map((ft) => (
<TypeCard
key={ft.id}
@@ -543,11 +596,20 @@ export const FuneralFinder = React.forwardRef<HTMLDivElement, FuneralFinderProps
<Typography variant="body2" component="span" sx={{ fontWeight: 600 }}>
Any preferences?
</Typography>
<Typography variant="caption" component="span" color="text.secondary" sx={{ ml: 0.75 }}>
<Typography
variant="caption"
component="span"
color="text.secondary"
sx={{ ml: 0.75 }}
>
(optional)
</Typography>
</Box>
<Box role="group" aria-label="Preferences" sx={{ display: 'flex', gap: 1, flexWrap: 'wrap' }}>
<Box
role="group"
aria-label="Preferences"
sx={{ display: 'flex', gap: 1, flexWrap: 'wrap' }}
>
{themeOptions.map((theme) => {
const isSelected = selectedThemes.includes(theme.id);
return (
@@ -573,7 +635,11 @@ export const FuneralFinder = React.forwardRef<HTMLDivElement, FuneralFinderProps
<Collapse in={activeStep === 4 && showServiceStep} timeout={250}>
<Box sx={{ mt: 3 }}>
<StepHeading>Would you like a service?</StepHeading>
<Box role="group" aria-label="Service preference" sx={{ display: 'flex', flexDirection: 'column', gap: 1 }}>
<Box
role="group"
aria-label="Service preference"
sx={{ display: 'flex', flexDirection: 'column', gap: 1 }}
>
{SERVICE_OPTIONS.map((opt) => (
<Chip
key={opt.value}
@@ -583,7 +649,11 @@ export const FuneralFinder = React.forwardRef<HTMLDivElement, FuneralFinderProps
onClick={() => selectService(opt.value)}
clickable
aria-pressed={serviceAnswered && servicePref === opt.value}
sx={{ justifyContent: 'flex-start', height: 44, borderRadius: 'var(--fa-border-radius-md)' }}
sx={{
justifyContent: 'flex-start',
height: 44,
borderRadius: 'var(--fa-border-radius-md)',
}}
/>
))}
</Box>

View File

@@ -41,12 +41,8 @@ export const BelowMasthead: Story = {
textAlign: 'center',
}}
>
<Box sx={{ fontSize: '2rem', fontWeight: 700, mb: 1 }}>
Funeral Arranger
</Box>
<Box sx={{ opacity: 0.8 }}>
Find trusted funeral directors near you
</Box>
<Box sx={{ fontSize: '2rem', fontWeight: 700, mb: 1 }}>Funeral Arranger</Box>
<Box sx={{ opacity: 0.8 }}>Find trusted funeral directors near you</Box>
</Box>
{/* Widget below masthead */}
<Box sx={{ maxWidth: 560, mx: 'auto', mt: -4, px: 2, position: 'relative', zIndex: 1 }}>

View File

@@ -103,7 +103,10 @@ function StepCircle({
transition: 'background-color 200ms ease, color 200ms ease',
...(usePrimary
? { bgcolor: 'var(--fa-color-brand-500)', color: 'common.white' }
: { bgcolor: 'var(--fa-color-brand-200, #EBDAC8)', color: 'var(--fa-color-brand-700, #8B4E0D)' }),
: {
bgcolor: 'var(--fa-color-brand-200, #EBDAC8)',
color: 'var(--fa-color-brand-700, #8B4E0D)',
}),
// Connector line from bottom of this circle toward the next
...(showConnector && {
'&::after': {
@@ -245,7 +248,8 @@ export const FuneralFinderV2 = React.forwardRef<HTMLDivElement, FuneralFinderV2P
}
: { lookingTo: false, planningFor: false, funeralType: false, location: false };
const hasErrors = submitted && (errs.lookingTo || errs.planningFor || errs.funeralType || errs.location);
const hasErrors =
submitted && (errs.lookingTo || errs.planningFor || errs.funeralType || errs.location);
// ─── Handlers ────────────────────────────────────────────────
const handleLookingTo = (e: SelectChangeEvent<string>) => {
@@ -311,11 +315,7 @@ export const FuneralFinderV2 = React.forwardRef<HTMLDivElement, FuneralFinderV2P
>
{heading}
</Typography>
<Typography
variant="body2"
color="text.secondary"
sx={{ textAlign: 'center', mb: 0 }}
>
<Typography variant="body2" color="text.secondary" sx={{ textAlign: 'center', mb: 0 }}>
{subheading}
</Typography>
<Divider sx={{ my: 3.5 }} />
@@ -326,7 +326,10 @@ export const FuneralFinderV2 = React.forwardRef<HTMLDivElement, FuneralFinderV2P
<Box sx={{ display: 'flex', gap: 2.5, alignItems: 'flex-end' }}>
<StepCircle step={1} completed={!!lookingTo} active showConnector />
<Box sx={{ flex: 1 }}>
<Typography variant="body1" sx={{ fontWeight: 600, mb: 1, color: 'var(--fa-color-brand-700)' }}>
<Typography
variant="body1"
sx={{ fontWeight: 600, mb: 1, color: 'var(--fa-color-brand-700)' }}
>
I&rsquo;m looking to&hellip;
</Typography>
<Select
@@ -352,7 +355,14 @@ export const FuneralFinderV2 = React.forwardRef<HTMLDivElement, FuneralFinderV2P
<Box sx={{ display: 'flex', gap: 2.5, alignItems: 'flex-end' }}>
<StepCircle step={2} completed={!!planningFor} showConnector />
<Box sx={{ flex: 1 }}>
<Typography variant="body1" sx={{ fontWeight: 600, mb: 1, color: lookingTo ? 'var(--fa-color-brand-700)' : 'text.disabled' }}>
<Typography
variant="body1"
sx={{
fontWeight: 600,
mb: 1,
color: lookingTo ? 'var(--fa-color-brand-700)' : 'text.disabled',
}}
>
I&rsquo;m planning for
</Typography>
<Select
@@ -383,7 +393,14 @@ export const FuneralFinderV2 = React.forwardRef<HTMLDivElement, FuneralFinderV2P
<Box sx={{ display: 'flex', gap: 2.5, alignItems: 'flex-end' }}>
<StepCircle step={3} completed={!!funeralType} showConnector />
<Box sx={{ flex: 1 }}>
<Typography variant="body1" sx={{ fontWeight: 600, mb: 1, color: step3Disabled ? 'text.disabled' : 'var(--fa-color-brand-700)' }}>
<Typography
variant="body1"
sx={{
fontWeight: 600,
mb: 1,
color: step3Disabled ? 'text.disabled' : 'var(--fa-color-brand-700)',
}}
>
Type of funeral
</Typography>
<Select
@@ -410,7 +427,14 @@ export const FuneralFinderV2 = React.forwardRef<HTMLDivElement, FuneralFinderV2P
<Box sx={{ display: 'flex', gap: 2.5, alignItems: 'flex-end' }}>
<StepCircle step={4} completed={location.trim().length >= 3} />
<Box sx={{ flex: 1 }}>
<Typography variant="body1" sx={{ fontWeight: 600, mb: 1, color: step4Disabled ? 'text.disabled' : 'var(--fa-color-brand-700)' }}>
<Typography
variant="body1"
sx={{
fontWeight: 600,
mb: 1,
color: step4Disabled ? 'text.disabled' : 'var(--fa-color-brand-700)',
}}
>
Looking for providers in
</Typography>
<Input

View File

@@ -33,8 +33,7 @@ export const BelowMasthead: Story = {
<Box>
<Box
sx={{
background:
'linear-gradient(160deg, #2C2E35 0%, #4C5B6B 60%, #6B3C13 100%)',
background: 'linear-gradient(160deg, #2C2E35 0%, #4C5B6B 60%, #6B3C13 100%)',
color: '#fff',
py: 8,
px: 4,

View File

@@ -75,28 +75,15 @@ const FUNERAL_TYPE_OPTIONS: { value: FuneralType; label: string }[] = [
/** Hoisted outside component to avoid re-creation on render */
const selectPlaceholder = (
<span style={{ color: 'var(--fa-color-text-disabled)' }}>
Select funeral type
</span>
<span style={{ color: 'var(--fa-color-text-disabled)' }}>Select funeral type</span>
);
// ─── Sub-components ──────────────────────────────────────────────────────────
/** Uppercase section label — overline style */
function SectionLabel({
children,
id,
}: {
children: React.ReactNode;
id?: string;
}) {
function SectionLabel({ children, id }: { children: React.ReactNode; id?: string }) {
return (
<Typography
variant="overline"
component="div"
id={id}
sx={{ color: 'text.secondary' }}
>
<Typography variant="overline" component="div" id={id} sx={{ color: 'text.secondary' }}>
{children}
</Typography>
);
@@ -138,8 +125,7 @@ const StatusCard = React.forwardRef<
cursor: 'pointer',
fontFamily: 'inherit',
textAlign: 'center',
transition:
'border-color 200ms ease, background-color 200ms ease, transform 100ms ease',
transition: 'border-color 200ms ease, background-color 200ms ease, transform 100ms ease',
'&:hover': {
borderColor: selected
? 'var(--fa-color-border-brand, #BA834E)'
@@ -164,9 +150,7 @@ const StatusCard = React.forwardRef<
fontWeight: 600,
display: 'block',
mb: 0.75,
color: selected
? 'var(--fa-color-text-brand, #B0610F)'
: 'text.primary',
color: selected ? 'var(--fa-color-text-brand, #B0610F)' : 'text.primary',
}}
>
{title}
@@ -253,317 +237,309 @@ const selectMenuProps = {
* Required fields: status + location (min 3 chars).
* Funeral type defaults to "show all" if not selected.
*/
export const FuneralFinderV3 = React.forwardRef<
HTMLDivElement,
FuneralFinderV3Props
>((props, ref) => {
const {
onSearch,
loading = false,
heading = 'Find funeral directors near you',
subheading =
"Tell us what you need and we\u2019ll show options in your area.",
sx,
} = props;
export const FuneralFinderV3 = React.forwardRef<HTMLDivElement, FuneralFinderV3Props>(
(props, ref) => {
const {
onSearch,
loading = false,
heading = 'Find funeral directors near you',
subheading = 'Tell us what you need and we\u2019ll show options in your area.',
sx,
} = props;
// ─── IDs for aria-labelledby ──────────────────────────────
const id = React.useId();
const statusLabelId = `${id}-status`;
const funeralTypeLabelId = `${id}-funeral-type`;
const locationLabelId = `${id}-location`;
// ─── IDs for aria-labelledby ──────────────────────────────
const id = React.useId();
const statusLabelId = `${id}-status`;
const funeralTypeLabelId = `${id}-funeral-type`;
const locationLabelId = `${id}-location`;
// ─── State ───────────────────────────────────────────────
const [status, setStatus] = React.useState<Status | ''>('immediate');
const [funeralType, setFuneralType] = React.useState<FuneralType | ''>('');
const [location, setLocation] = React.useState('');
const [errors, setErrors] = React.useState<{
status?: boolean;
location?: boolean;
}>({});
// ─── State ───────────────────────────────────────────────
const [status, setStatus] = React.useState<Status | ''>('immediate');
const [funeralType, setFuneralType] = React.useState<FuneralType | ''>('');
const [location, setLocation] = React.useState('');
const [errors, setErrors] = React.useState<{
status?: boolean;
location?: boolean;
}>({});
// ─── Refs ────────────────────────────────────────────────
const statusSectionRef = React.useRef<HTMLDivElement>(null);
const locationSectionRef = React.useRef<HTMLDivElement>(null);
const locationInputRef = React.useRef<HTMLInputElement>(null);
const cardRefs = React.useRef<(HTMLButtonElement | null)[]>([null, null]);
// ─── Refs ────────────────────────────────────────────────
const statusSectionRef = React.useRef<HTMLDivElement>(null);
const locationSectionRef = React.useRef<HTMLDivElement>(null);
const locationInputRef = React.useRef<HTMLInputElement>(null);
const cardRefs = React.useRef<(HTMLButtonElement | null)[]>([null, null]);
// ─── Clear errors as fields are filled ───────────────────
const prevStatus = React.useRef(status);
React.useEffect(() => {
if (status !== prevStatus.current) {
prevStatus.current = status;
if (status && errors.status) {
setErrors((prev) => ({ ...prev, status: false }));
// ─── Clear errors as fields are filled ───────────────────
const prevStatus = React.useRef(status);
React.useEffect(() => {
if (status !== prevStatus.current) {
prevStatus.current = status;
if (status && errors.status) {
setErrors((prev) => ({ ...prev, status: false }));
}
}
}
}, [status, errors.status]);
}, [status, errors.status]);
const prevLocation = React.useRef(location);
React.useEffect(() => {
if (location !== prevLocation.current) {
prevLocation.current = location;
if (location.trim().length >= 3 && errors.location) {
setErrors((prev) => ({ ...prev, location: false }));
const prevLocation = React.useRef(location);
React.useEffect(() => {
if (location !== prevLocation.current) {
prevLocation.current = location;
if (location.trim().length >= 3 && errors.location) {
setErrors((prev) => ({ ...prev, location: false }));
}
}
}
}, [location, errors.location]);
}, [location, errors.location]);
// ─── Radiogroup keyboard nav (WAI-ARIA pattern) ──────────
const activeStatusIndex = status
? STATUS_OPTIONS.findIndex((o) => o.key === status)
: 0;
// ─── Radiogroup keyboard nav (WAI-ARIA pattern) ──────────
const activeStatusIndex = status ? STATUS_OPTIONS.findIndex((o) => o.key === status) : 0;
const handleStatusKeyDown = (e: React.KeyboardEvent) => {
const isNext = e.key === 'ArrowRight' || e.key === 'ArrowDown';
const isPrev = e.key === 'ArrowLeft' || e.key === 'ArrowUp';
if (!isNext && !isPrev) return;
e.preventDefault();
const current = cardRefs.current.indexOf(
e.target as HTMLButtonElement,
);
if (current === -1) return;
const next = isNext
? Math.min(current + 1, STATUS_OPTIONS.length - 1)
: Math.max(current - 1, 0);
if (next !== current) {
cardRefs.current[next]?.focus();
setStatus(STATUS_OPTIONS[next].key);
}
};
const handleStatusKeyDown = (e: React.KeyboardEvent) => {
const isNext = e.key === 'ArrowRight' || e.key === 'ArrowDown';
const isPrev = e.key === 'ArrowLeft' || e.key === 'ArrowUp';
if (!isNext && !isPrev) return;
e.preventDefault();
const current = cardRefs.current.indexOf(e.target as HTMLButtonElement);
if (current === -1) return;
const next = isNext
? Math.min(current + 1, STATUS_OPTIONS.length - 1)
: Math.max(current - 1, 0);
if (next !== current) {
cardRefs.current[next]?.focus();
setStatus(STATUS_OPTIONS[next].key);
}
};
// ─── Handlers ────────────────────────────────────────────
const handleFuneralType = (e: SelectChangeEvent<string>) => {
setFuneralType(e.target.value as FuneralType);
};
// ─── Handlers ────────────────────────────────────────────
const handleFuneralType = (e: SelectChangeEvent<string>) => {
setFuneralType(e.target.value as FuneralType);
};
const handleSubmit = () => {
if (!status) {
setErrors({ status: true });
statusSectionRef.current?.scrollIntoView({
behavior: 'smooth',
block: 'center',
const handleSubmit = () => {
if (!status) {
setErrors({ status: true });
statusSectionRef.current?.scrollIntoView({
behavior: 'smooth',
block: 'center',
});
return;
}
if (location.trim().length < 3) {
setErrors({ location: true });
locationSectionRef.current?.scrollIntoView({
behavior: 'smooth',
block: 'center',
});
locationInputRef.current?.focus();
return;
}
setErrors({});
onSearch?.({
status,
funeralType: funeralType || 'show-all',
location: location.trim(),
});
return;
}
if (location.trim().length < 3) {
setErrors({ location: true });
locationSectionRef.current?.scrollIntoView({
behavior: 'smooth',
block: 'center',
});
locationInputRef.current?.focus();
return;
}
setErrors({});
onSearch?.({
status,
funeralType: funeralType || 'show-all',
location: location.trim(),
});
};
};
// ─── Render ──────────────────────────────────────────────
return (
<Box
ref={ref}
role="search"
aria-label="Find funeral directors"
sx={[
{
bgcolor: 'var(--fa-color-surface-raised, #fff)',
borderRadius: 'var(--fa-card-border-radius-default, 8px)',
boxShadow: 'var(--fa-card-shadow-default)',
px: { xs: 3.5, sm: 5 },
py: { xs: 4, sm: 5 },
display: 'flex',
flexDirection: 'column',
gap: 4,
},
...(Array.isArray(sx) ? sx : [sx]),
]}
>
{/* ── Header ──────────────────────────────────────────── */}
<Box sx={{ textAlign: 'center' }}>
<Typography
variant="h3"
component="h2"
sx={{
fontFamily: 'var(--fa-font-family-display)',
fontWeight: 400,
mb: 1,
}}
>
{heading}
</Typography>
<Typography variant="body2" color="text.secondary">
{subheading}
</Typography>
</Box>
<Divider />
{/* ── How can we help ─────────────────────────────────── */}
<Box ref={statusSectionRef}>
<SectionLabel id={statusLabelId}>How Can We Help</SectionLabel>
<Box
role="radiogroup"
aria-labelledby={statusLabelId}
sx={{
display: 'grid',
gridTemplateColumns: { xs: '1fr', sm: '1fr 1fr' },
gap: 2,
mt: 2,
}}
>
{STATUS_OPTIONS.map((opt, i) => (
<StatusCard
key={opt.key}
ref={(el) => {
cardRefs.current[i] = el;
}}
title={opt.title}
description={opt.description}
selected={status === opt.key}
onClick={() => setStatus(opt.key)}
tabIndex={i === activeStatusIndex ? 0 : -1}
onKeyDown={handleStatusKeyDown}
/>
))}
</Box>
<Box aria-live="polite" sx={{ textAlign: 'center' }}>
{errors.status && (
<Typography
variant="caption"
role="alert"
sx={{
color: 'var(--fa-color-text-brand, #B0610F)',
display: 'block',
mt: 1,
}}
>
Please select how we can help
</Typography>
)}
</Box>
</Box>
{/* ── Funeral Type ────────────────────────────────────── */}
<Box>
<SectionLabel id={funeralTypeLabelId}>Funeral Type</SectionLabel>
<Box sx={{ mt: 2 }}>
<Select
value={funeralType}
onChange={handleFuneralType}
displayEmpty
renderValue={(v) =>
v
? FUNERAL_TYPE_OPTIONS.find((o) => o.value === v)?.label
: selectPlaceholder
}
MenuProps={selectMenuProps}
// ─── Render ──────────────────────────────────────────────
return (
<Box
ref={ref}
role="search"
aria-label="Find funeral directors"
sx={[
{
bgcolor: 'var(--fa-color-surface-raised, #fff)',
borderRadius: 'var(--fa-card-border-radius-default, 8px)',
boxShadow: 'var(--fa-card-shadow-default)',
px: { xs: 3.5, sm: 5 },
py: { xs: 4, sm: 5 },
display: 'flex',
flexDirection: 'column',
gap: 4,
},
...(Array.isArray(sx) ? sx : [sx]),
]}
>
{/* ── Header ──────────────────────────────────────────── */}
<Box sx={{ textAlign: 'center' }}>
<Typography
variant="h3"
component="h2"
sx={{
...fieldBaseSx,
'& .MuiSelect-select': {
...fieldInputStyles,
minHeight: 'unset !important',
},
'& .MuiSelect-icon': {
color: 'var(--fa-color-text-disabled)',
right: 12,
},
fontFamily: 'var(--fa-font-family-display)',
fontWeight: 400,
mb: 1,
}}
inputProps={{ 'aria-labelledby': funeralTypeLabelId }}
>
{FUNERAL_TYPE_OPTIONS.map((o) => (
<MenuItem key={o.value} value={o.value}>
{o.label}
</MenuItem>
))}
</Select>
{heading}
</Typography>
<Typography variant="body2" color="text.secondary">
{subheading}
</Typography>
</Box>
</Box>
{/* ── Location ────────────────────────────────────────── */}
<Box ref={locationSectionRef}>
<SectionLabel id={locationLabelId}>Location</SectionLabel>
<Box sx={{ mt: 2 }}>
<OutlinedInput
value={location}
onChange={(e) => setLocation(e.target.value)}
placeholder="Enter suburb or postcode"
inputRef={locationInputRef}
startAdornment={
<InputAdornment position="start" sx={{ ml: 0.5 }}>
<LocationOnOutlinedIcon
sx={{
fontSize: 20,
color: 'var(--fa-color-text-disabled)',
}}
/>
</InputAdornment>
}
onKeyDown={(e) => {
if (e.key === 'Enter') handleSubmit();
}}
<Divider />
{/* ── How can we help ─────────────────────────────────── */}
<Box ref={statusSectionRef}>
<SectionLabel id={statusLabelId}>How Can We Help</SectionLabel>
<Box
role="radiogroup"
aria-labelledby={statusLabelId}
sx={{
...fieldBaseSx,
'& .MuiOutlinedInput-input': {
...fieldInputStyles,
'&::placeholder': {
color: 'var(--fa-color-text-disabled)',
opacity: 1,
},
},
display: 'grid',
gridTemplateColumns: { xs: '1fr', sm: '1fr 1fr' },
gap: 2,
mt: 2,
}}
inputProps={{
'aria-labelledby': locationLabelId,
'aria-required': true,
}}
/>
>
{STATUS_OPTIONS.map((opt, i) => (
<StatusCard
key={opt.key}
ref={(el) => {
cardRefs.current[i] = el;
}}
title={opt.title}
description={opt.description}
selected={status === opt.key}
onClick={() => setStatus(opt.key)}
tabIndex={i === activeStatusIndex ? 0 : -1}
onKeyDown={handleStatusKeyDown}
/>
))}
</Box>
<Box aria-live="polite" sx={{ textAlign: 'center' }}>
{errors.status && (
<Typography
variant="caption"
role="alert"
sx={{
color: 'var(--fa-color-text-brand, #B0610F)',
display: 'block',
mt: 1,
}}
>
Please select how we can help
</Typography>
)}
</Box>
</Box>
<Box aria-live="polite">
{errors.location && (
<Typography
variant="caption"
role="alert"
{/* ── Funeral Type ────────────────────────────────────── */}
<Box>
<SectionLabel id={funeralTypeLabelId}>Funeral Type</SectionLabel>
<Box sx={{ mt: 2 }}>
<Select
value={funeralType}
onChange={handleFuneralType}
displayEmpty
renderValue={(v) =>
v ? FUNERAL_TYPE_OPTIONS.find((o) => o.value === v)?.label : selectPlaceholder
}
MenuProps={selectMenuProps}
sx={{
color: 'var(--fa-color-text-brand, #B0610F)',
display: 'block',
mt: 1,
...fieldBaseSx,
'& .MuiSelect-select': {
...fieldInputStyles,
minHeight: 'unset !important',
},
'& .MuiSelect-icon': {
color: 'var(--fa-color-text-disabled)',
right: 12,
},
}}
inputProps={{ 'aria-labelledby': funeralTypeLabelId }}
>
Please enter a suburb or postcode
</Typography>
)}
{FUNERAL_TYPE_OPTIONS.map((o) => (
<MenuItem key={o.value} value={o.value}>
{o.label}
</MenuItem>
))}
</Select>
</Box>
</Box>
{/* ── Location ────────────────────────────────────────── */}
<Box ref={locationSectionRef}>
<SectionLabel id={locationLabelId}>Location</SectionLabel>
<Box sx={{ mt: 2 }}>
<OutlinedInput
value={location}
onChange={(e) => setLocation(e.target.value)}
placeholder="Enter suburb or postcode"
inputRef={locationInputRef}
startAdornment={
<InputAdornment position="start" sx={{ ml: 0.5 }}>
<LocationOnOutlinedIcon
sx={{
fontSize: 20,
color: 'var(--fa-color-text-disabled)',
}}
/>
</InputAdornment>
}
onKeyDown={(e) => {
if (e.key === 'Enter') handleSubmit();
}}
sx={{
...fieldBaseSx,
'& .MuiOutlinedInput-input': {
...fieldInputStyles,
'&::placeholder': {
color: 'var(--fa-color-text-disabled)',
opacity: 1,
},
},
}}
inputProps={{
'aria-labelledby': locationLabelId,
'aria-required': true,
}}
/>
</Box>
<Box aria-live="polite">
{errors.location && (
<Typography
variant="caption"
role="alert"
sx={{
color: 'var(--fa-color-text-brand, #B0610F)',
display: 'block',
mt: 1,
}}
>
Please enter a suburb or postcode
</Typography>
)}
</Box>
</Box>
<Divider />
{/* ── CTA ─────────────────────────────────────────────── */}
<Box>
<Button
variant="contained"
size="large"
fullWidth
loading={loading}
endIcon={!loading ? <ArrowForwardIcon /> : undefined}
onClick={handleSubmit}
sx={{ minHeight: 52 }}
>
Find Funeral Directors
</Button>
<Typography
variant="captionSm"
color="text.secondary"
sx={{ textAlign: 'center', display: 'block', mt: 1.5 }}
>
Free to use &middot; No obligation
</Typography>
</Box>
</Box>
<Divider />
{/* ── CTA ─────────────────────────────────────────────── */}
<Box>
<Button
variant="contained"
size="large"
fullWidth
loading={loading}
endIcon={!loading ? <ArrowForwardIcon /> : undefined}
onClick={handleSubmit}
sx={{ minHeight: 52 }}
>
Find Funeral Directors
</Button>
<Typography
variant="captionSm"
color="text.secondary"
sx={{ textAlign: 'center', display: 'block', mt: 1.5 }}
>
Free to use &middot; No obligation
</Typography>
</Box>
</Box>
);
});
);
},
);
FuneralFinderV3.displayName = 'FuneralFinderV3';
export default FuneralFinderV3;

View File

@@ -77,11 +77,7 @@ export const WithCTA: Story = {
export const WithPageContent: Story = {
render: () => (
<Box>
<Navigation
logo={<FALogo />}
items={defaultItems}
ctaLabel="Start planning"
/>
<Navigation logo={<FALogo />} items={defaultItems} ctaLabel="Start planning" />
<Box
sx={{
maxWidth: 'lg',
@@ -94,8 +90,8 @@ export const WithPageContent: Story = {
Find a funeral director
</Typography>
<Typography variant="body1" color="text.secondary" sx={{ mb: 4, maxWidth: 600 }}>
Compare trusted funeral directors in your area. View services,
pricing, and reviews to find the right support for your family.
Compare trusted funeral directors in your area. View services, pricing, and reviews to
find the right support for your family.
</Typography>
{Array.from({ length: 8 }).map((_, i) => (
<Box

View File

@@ -156,11 +156,7 @@ export const Navigation = React.forwardRef<HTMLDivElement, NavigationProps>(
))}
{ctaLabel && (
<Button
variant="contained"
size="medium"
onClick={onCtaClick}
>
<Button variant="contained" size="medium" onClick={onCtaClick}>
{ctaLabel}
</Button>
)}
@@ -193,14 +189,8 @@ export const Navigation = React.forwardRef<HTMLDivElement, NavigationProps>(
bgcolor: 'var(--fa-color-surface-subtle)',
}}
>
<Box sx={{ display: 'flex', alignItems: 'center' }}>
{logo}
</Box>
<IconButton
aria-label="Close menu"
onClick={handleDrawerToggle}
size="small"
>
<Box sx={{ display: 'flex', alignItems: 'center' }}>{logo}</Box>
<IconButton aria-label="Close menu" onClick={handleDrawerToggle} size="small">
<CloseIcon />
</IconButton>
</Box>

View File

@@ -10,44 +10,136 @@ import { Button } from '../../atoms/Button';
import { Navigation } from '../Navigation';
import ArrowBackIcon from '@mui/icons-material/ArrowBack';
const DEMO_IMAGE = 'https://images.unsplash.com/photo-1600585154340-be6161a56a0c?w=400&h=300&fit=crop';
const DEMO_IMAGE =
'https://images.unsplash.com/photo-1600585154340-be6161a56a0c?w=400&h=300&fit=crop';
const essentials = [
{ name: 'Accommodation', price: 1500, info: 'Refrigerated holding of the deceased prior to the funeral service.' },
{ name: 'Death Registration Certificate', price: 1500, info: 'Lodgement of death registration with NSW Registry of Births, Deaths & Marriages.' },
{ name: 'Doctor Fee for Cremation', price: 1500, info: 'Statutory medical referee fee required for all cremations in NSW.' },
{ name: 'NSW Government Levy — Cremation', price: 1500, info: 'NSW Government cremation levy as set by the Department of Health.' },
{ name: 'Professional Mortuary Care', price: 1500, info: 'Preparation and care of the deceased.' },
{ name: 'Professional Service Fee', price: 1500, info: 'Coordination of all funeral arrangements and services.' },
{ name: 'Allowance for Coffin', price: 1500, isAllowance: true, info: 'Allowance amount — upgrade options available during arrangement.' },
{ name: 'Allowance for Crematorium', price: 1500, isAllowance: true, info: 'Allowance for crematorium fees — varies by location.' },
{ name: 'Allowance for Hearse', price: 1500, isAllowance: true, info: 'Allowance for hearse transfer — distance surcharges may apply.' },
{
name: 'Accommodation',
price: 1500,
info: 'Refrigerated holding of the deceased prior to the funeral service.',
},
{
name: 'Death Registration Certificate',
price: 1500,
info: 'Lodgement of death registration with NSW Registry of Births, Deaths & Marriages.',
},
{
name: 'Doctor Fee for Cremation',
price: 1500,
info: 'Statutory medical referee fee required for all cremations in NSW.',
},
{
name: 'NSW Government Levy — Cremation',
price: 1500,
info: 'NSW Government cremation levy as set by the Department of Health.',
},
{
name: 'Professional Mortuary Care',
price: 1500,
info: 'Preparation and care of the deceased.',
},
{
name: 'Professional Service Fee',
price: 1500,
info: 'Coordination of all funeral arrangements and services.',
},
{
name: 'Allowance for Coffin',
price: 1500,
isAllowance: true,
info: 'Allowance amount — upgrade options available during arrangement.',
},
{
name: 'Allowance for Crematorium',
price: 1500,
isAllowance: true,
info: 'Allowance for crematorium fees — varies by location.',
},
{
name: 'Allowance for Hearse',
price: 1500,
isAllowance: true,
info: 'Allowance for hearse transfer — distance surcharges may apply.',
},
];
const complimentary = [
{ name: 'Dressing Fee', info: 'Dressing and preparation of the deceased — included at no charge.' },
{
name: 'Dressing Fee',
info: 'Dressing and preparation of the deceased — included at no charge.',
},
{ name: 'Viewing Fee', info: 'One private family viewing — included at no charge.' },
];
const extras = {
heading: 'Extras',
items: [
{ name: 'Allowance for Flowers', price: 1500, isAllowance: true, info: 'Seasonal floral arrangements for the service.' },
{ name: 'Allowance for Master of Ceremonies', price: 1500, isAllowance: true, info: 'Professional celebrant or MC for the funeral service.' },
{ name: 'After Business Hours Service Surcharge', price: 1500, info: 'Additional fee for services held outside standard business hours.' },
{ name: 'After Hours Prayers', price: 1500, info: 'Evening prayer service at the funeral home.' },
{ name: 'Coffin Bearing by Funeral Directors', price: 1500, info: 'Professional pallbearing by funeral directors.' },
{ name: 'Digital Recording', price: 1500, info: 'Professional video recording of the funeral service.' },
{
name: 'Allowance for Flowers',
price: 1500,
isAllowance: true,
info: 'Seasonal floral arrangements for the service.',
},
{
name: 'Allowance for Master of Ceremonies',
price: 1500,
isAllowance: true,
info: 'Professional celebrant or MC for the funeral service.',
},
{
name: 'After Business Hours Service Surcharge',
price: 1500,
info: 'Additional fee for services held outside standard business hours.',
},
{
name: 'After Hours Prayers',
price: 1500,
info: 'Evening prayer service at the funeral home.',
},
{
name: 'Coffin Bearing by Funeral Directors',
price: 1500,
info: 'Professional pallbearing by funeral directors.',
},
{
name: 'Digital Recording',
price: 1500,
info: 'Professional video recording of the funeral service.',
},
],
};
const termsText = '* This package includes a funeral service at a chapel or a church with a funeral procession following to the crematorium. It includes many of the most commonly selected funeral options preselected for you. Many people choose this package for the extended funeral rituals — of course, you can tailor the funeral service to meet your needs and budget as you go through the selections.';
const termsText =
'* This package includes a funeral service at a chapel or a church with a funeral procession following to the crematorium. It includes many of the most commonly selected funeral options preselected for you. Many people choose this package for the extended funeral rituals — of course, you can tailor the funeral service to meet your needs and budget as you go through the selections.';
const packages = [
{ id: 'everyday', name: 'Everyday Funeral Package', price: 900, description: 'Our most popular package with all essential services included. Suitable for a traditional chapel or church service.' },
{ id: 'deluxe', name: 'Deluxe Funeral Package', price: 1200, description: 'An enhanced package with premium coffin and additional floral arrangements.' },
{ id: 'essential', name: 'Essential Funeral Package', price: 600, description: 'A simple, dignified service covering all necessary arrangements.' },
{ id: 'catholic', name: 'Catholic Service', price: 950, description: 'A service tailored for Catholic traditions including prayers and church ceremony.' },
{
id: 'everyday',
name: 'Everyday Funeral Package',
price: 900,
description:
'Our most popular package with all essential services included. Suitable for a traditional chapel or church service.',
},
{
id: 'deluxe',
name: 'Deluxe Funeral Package',
price: 1200,
description: 'An enhanced package with premium coffin and additional floral arrangements.',
},
{
id: 'essential',
name: 'Essential Funeral Package',
price: 600,
description: 'A simple, dignified service covering all necessary arrangements.',
},
{
id: 'catholic',
name: 'Catholic Service',
price: 950,
description:
'A service tailored for Catholic traditions including prayers and church ceremony.',
},
];
const funeralTypes = ['All', 'Cremation', 'Burial', 'Memorial', 'Catholic', 'Direct Cremation'];
@@ -101,9 +193,7 @@ export const CompareLoading: Story = {
args: {
name: 'Everyday Funeral Package',
price: 900,
sections: [
{ heading: 'Essentials', items: essentials.slice(0, 4) },
],
sections: [{ heading: 'Essentials', items: essentials.slice(0, 4) }],
total: 6000,
onArrange: () => alert('Make Arrangement'),
onCompare: () => {},

View File

@@ -155,15 +155,14 @@ export const PackageDetail = React.forwardRef<HTMLDivElement, PackageDetailProps
<Typography variant="h3" component="h2">
{name}
</Typography>
<Typography
variant="h5"
sx={{ mt: 0.5, color: 'primary.main', fontWeight: 600 }}
>
<Typography variant="h5" sx={{ mt: 0.5, color: 'primary.main', fontWeight: 600 }}>
${price.toLocaleString('en-AU')}
</Typography>
{/* CTA buttons */}
<Box sx={{ display: 'flex', flexDirection: { xs: 'column', sm: 'row' }, gap: 1.5, mt: 2.5 }}>
<Box
sx={{ display: 'flex', flexDirection: { xs: 'column', sm: 'row' }, gap: 1.5, mt: 2.5 }}
>
<Button
variant="contained"
size="large"
@@ -198,9 +197,7 @@ export const PackageDetail = React.forwardRef<HTMLDivElement, PackageDetailProps
))}
{/* Total — separates included content from extras */}
{total != null && (
<LineItem name="Total" price={total} variant="total" />
)}
{total != null && <LineItem name="Total" price={total} variant="total" />}
{/* Extras — additional cost items after the total */}
{extras && extras.items.length > 0 && (

View File

@@ -1 +1,6 @@
export { PackageDetail, type PackageDetailProps, type PackageSection, type PackageLineItem } from './PackageDetail';
export {
PackageDetail,
type PackageDetailProps,
type PackageSection,
type PackageLineItem,
} from './PackageDetail';

View File

@@ -37,10 +37,30 @@ const serviceTypes = [
];
const coffinOptions = [
{ id: 'eco', name: 'Eco Willow', price: 850, description: 'Handwoven natural willow. Biodegradable and sustainable.' },
{ id: 'classic', name: 'Classic Maple', price: 1400, description: 'Solid maple with satin finish and brass handles.' },
{ id: 'premium', name: 'Premium Oak', price: 2200, description: 'Quarter-sawn oak with high-gloss lacquer and gold-plated handles.' },
{ id: 'simple', name: 'Simple Pine', price: 600, description: 'Unfinished pine. Can be personalised with paint, photos, or messages.' },
{
id: 'eco',
name: 'Eco Willow',
price: 850,
description: 'Handwoven natural willow. Biodegradable and sustainable.',
},
{
id: 'classic',
name: 'Classic Maple',
price: 1400,
description: 'Solid maple with satin finish and brass handles.',
},
{
id: 'premium',
name: 'Premium Oak',
price: 2200,
description: 'Quarter-sawn oak with high-gloss lacquer and gold-plated handles.',
},
{
id: 'simple',
name: 'Simple Pine',
price: 600,
description: 'Unfinished pine. Can be personalised with paint, photos, or messages.',
},
];
const meta: Meta<typeof ServiceSelector> = {
@@ -72,7 +92,7 @@ type Story = StoryObj<typeof ServiceSelector>;
export const Default: Story = {
args: {
heading: 'Choose a service type',
subheading: 'Select the type of service you\'d like to arrange. Prices are starting estimates.',
subheading: "Select the type of service you'd like to arrange. Prices are starting estimates.",
items: serviceTypes,
continueLabel: 'Continue',
},
@@ -180,7 +200,13 @@ export const WithDisabledOptions: Story = {
const [selected, setSelected] = useState<string | undefined>();
const items = serviceTypes.map((item) =>
item.id === 'memorial' ? { ...item, disabled: true, description: item.description + ' (Currently unavailable at this location.)' } : item,
item.id === 'memorial'
? {
...item,
disabled: true,
description: item.description + ' (Currently unavailable at this location.)',
}
: item,
);
return (
@@ -227,7 +253,11 @@ export const InArrangementFlow: Story = {
maxDescriptionLines={2}
/>
<Typography variant="captionSm" color="text.secondary" sx={{ mt: 3, textAlign: 'center', display: 'block' }}>
<Typography
variant="captionSm"
color="text.secondary"
sx={{ mt: 3, textAlign: 'center', display: 'block' }}
>
All prices are estimates and may vary based on your specific requirements.
</Typography>
</Box>

View File

@@ -92,13 +92,7 @@ export const ServiceSelector = React.forwardRef<HTMLDivElement, ServiceSelectorP
const isContinueDisabled = continueDisabled ?? nothingSelected;
return (
<Box
ref={ref}
sx={[
{ width: '100%' },
...(Array.isArray(sx) ? sx : [sx]),
]}
>
<Box ref={ref} sx={[{ width: '100%' }, ...(Array.isArray(sx) ? sx : [sx])]}>
{/* Header */}
<Box sx={{ mb: 3 }}>
<Typography variant="h4" component="h2" sx={{ mb: subheading ? 1 : 0 }}>