Compare commits

..

1 Commits

Author SHA1 Message Date
af8956f130 Strip AI tooling and working docs for dev push 2026-04-13 15:49:49 +10:00
8 changed files with 130 additions and 341 deletions

View File

@@ -41,6 +41,10 @@ export interface FuneralFinderV3Props {
onSearch?: (params: FuneralFinderV3SearchParams) => void; onSearch?: (params: FuneralFinderV3SearchParams) => void;
/** Shows loading state on the CTA */ /** Shows loading state on the CTA */
loading?: boolean; loading?: boolean;
/** Optional heading override */
heading?: string;
/** Optional subheading override */
subheading?: string;
/** MUI sx override for the root container */ /** MUI sx override for the root container */
sx?: SxProps<Theme>; sx?: SxProps<Theme>;
} }
@@ -247,7 +251,13 @@ const selectMenuProps = {
*/ */
export const FuneralFinderV3 = React.forwardRef<HTMLDivElement, FuneralFinderV3Props>( export const FuneralFinderV3 = React.forwardRef<HTMLDivElement, FuneralFinderV3Props>(
(props, ref) => { (props, ref) => {
const { onSearch, loading = false, sx } = props; const {
onSearch,
loading = false,
heading = 'Find funeral directors near you',
subheading,
sx,
} = props;
// ─── IDs for aria-labelledby ────────────────────────────── // ─── IDs for aria-labelledby ──────────────────────────────
const id = React.useId(); const id = React.useId();
@@ -382,6 +392,29 @@ export const FuneralFinderV3 = React.forwardRef<HTMLDivElement, FuneralFinderV3P
...(Array.isArray(sx) ? sx : [sx]), ...(Array.isArray(sx) ? sx : [sx]),
]} ]}
> >
{/* ── Header ──────────────────────────────────────────── */}
<Box sx={{ textAlign: 'center' }}>
<Typography
variant="h3"
component="h2"
sx={{
fontFamily: 'var(--fa-font-family-display)',
fontWeight: 600,
fontSize: { xs: '1.25rem', sm: '1.5rem' },
mb: subheading ? 1 : 0,
}}
>
{heading}
</Typography>
{subheading && (
<Typography variant="body2" color="text.secondary">
{subheading}
</Typography>
)}
</Box>
<Divider />
{/* ── How can we help ─────────────────────────────────── */} {/* ── How can we help ─────────────────────────────────── */}
<Box ref={statusSectionRef}> <Box ref={statusSectionRef}>
<SectionLabel id={statusLabelId}>How Can We Help</SectionLabel> <SectionLabel id={statusLabelId}>How Can We Help</SectionLabel>

View File

@@ -143,28 +143,3 @@ export const ExtendedNavigation: Story = {
ctaLabel: 'Start planning', ctaLabel: 'Start planning',
}, },
}; };
// --- With Dropdown -----------------------------------------------------------
/** Items with `children` render as a dropdown on desktop and a collapsible
* section in the mobile drawer */
export const WithDropdown: Story = {
args: {
logo: <FALogo />,
items: [
{
label: 'Locations',
children: [
{ label: 'Melbourne', href: '/locations/melbourne' },
{ label: 'Brisbane', href: '/locations/brisbane' },
{ label: 'Sydney', href: '/locations/sydney' },
{ label: 'South Coast NSW', href: '/locations/south-coast-nsw' },
{ label: 'Central Coast NSW', href: '/locations/central-coast-nsw' },
],
},
{ label: 'FAQ', href: '/faq' },
{ label: 'Contact Us', href: '/contact' },
{ label: 'Log in', href: '/login' },
],
},
};

View File

@@ -6,14 +6,9 @@ import Drawer from '@mui/material/Drawer';
import List from '@mui/material/List'; import List from '@mui/material/List';
import ListItemButton from '@mui/material/ListItemButton'; import ListItemButton from '@mui/material/ListItemButton';
import ListItemText from '@mui/material/ListItemText'; import ListItemText from '@mui/material/ListItemText';
import Menu from '@mui/material/Menu';
import MenuItem from '@mui/material/MenuItem';
import Collapse from '@mui/material/Collapse';
import useMediaQuery from '@mui/material/useMediaQuery'; import useMediaQuery from '@mui/material/useMediaQuery';
import MenuIcon from '@mui/icons-material/Menu'; import MenuIcon from '@mui/icons-material/Menu';
import CloseIcon from '@mui/icons-material/Close'; import CloseIcon from '@mui/icons-material/Close';
import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
import ExpandLessIcon from '@mui/icons-material/ExpandLess';
import type { SxProps, Theme } from '@mui/material/styles'; import type { SxProps, Theme } from '@mui/material/styles';
import { IconButton } from '../../atoms/IconButton'; import { IconButton } from '../../atoms/IconButton';
import { Link } from '../../atoms/Link'; import { Link } from '../../atoms/Link';
@@ -23,16 +18,14 @@ import { Divider } from '../../atoms/Divider';
// ─── Types ─────────────────────────────────────────────────────────────────── // ─── Types ───────────────────────────────────────────────────────────────────
/** A navigation link item. May have children to render as a dropdown. */ /** A navigation link item */
export interface NavItem { export interface NavItem {
/** Display label */ /** Display label */
label: string; label: string;
/** URL to navigate to (ignored when `children` is provided) */ /** URL to navigate to */
href?: string; href: string;
/** Click handler (alternative to href for SPA navigation) */ /** Click handler (alternative to href for SPA navigation) */
onClick?: () => void; onClick?: () => void;
/** Sub-items rendered as a dropdown (desktop) or collapsible (mobile) */
children?: NavItem[];
} }
/** Props for the FA Navigation organism */ /** Props for the FA Navigation organism */
@@ -51,163 +44,6 @@ export interface NavigationProps {
sx?: SxProps<Theme>; sx?: SxProps<Theme>;
} }
// ─── Desktop dropdown link ───────────────────────────────────────────────────
interface DesktopDropdownProps {
item: NavItem;
}
const DesktopDropdown: React.FC<DesktopDropdownProps> = ({ item }) => {
const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null);
const open = Boolean(anchorEl);
const handleOpen = (event: React.MouseEvent<HTMLElement>) => setAnchorEl(event.currentTarget);
const handleClose = () => setAnchorEl(null);
return (
<>
<Box
component="button"
type="button"
aria-haspopup="menu"
aria-expanded={open}
onClick={handleOpen}
sx={{
background: 'none',
border: 'none',
padding: 0,
cursor: 'pointer',
color: 'var(--fa-color-brand-900)',
fontFamily: 'inherit',
fontWeight: 600,
fontSize: '1rem',
'&:hover': {
color: 'primary.main',
},
}}
>
{item.label}
</Box>
<Menu
anchorEl={anchorEl}
open={open}
onClose={handleClose}
anchorOrigin={{ vertical: 'bottom', horizontal: 'left' }}
transformOrigin={{ vertical: 'top', horizontal: 'left' }}
slotProps={{
paper: {
sx: {
mt: 1,
minWidth: 200,
borderRadius: 'var(--fa-border-radius-md, 8px)',
boxShadow: '0 8px 24px rgba(0,0,0,0.08)',
},
},
}}
>
{item.children?.map((child) => (
<MenuItem
key={child.label}
component="a"
href={child.href}
onClick={(e: React.MouseEvent) => {
if (child.onClick) {
e.preventDefault();
child.onClick();
}
handleClose();
}}
sx={{
color: 'var(--fa-color-brand-900)',
fontWeight: 500,
py: 1.25,
'&:hover': {
bgcolor: 'var(--fa-color-brand-100)',
color: 'primary.main',
},
}}
>
{child.label}
</MenuItem>
))}
</Menu>
</>
);
};
// ─── Mobile collapsible item ─────────────────────────────────────────────────
interface MobileCollapsibleProps {
item: NavItem;
onItemClick: () => void;
}
const MobileCollapsible: React.FC<MobileCollapsibleProps> = ({ item, onItemClick }) => {
const [open, setOpen] = React.useState(false);
return (
<>
<ListItemButton
onClick={() => setOpen((prev) => !prev)}
aria-expanded={open}
sx={{
py: 1.5,
px: 3,
minHeight: 44,
'&:hover': {
bgcolor: 'var(--fa-color-brand-100)',
},
}}
>
<ListItemText
primary={item.label}
primaryTypographyProps={{
fontWeight: 500,
fontSize: '1rem',
}}
/>
{open ? <ExpandLessIcon /> : <ExpandMoreIcon />}
</ListItemButton>
<Collapse in={open} timeout="auto" unmountOnExit>
<List component="div" disablePadding>
{item.children?.map((child) => (
<ListItemButton
key={child.label}
component="a"
href={child.href}
onClick={(e: React.MouseEvent) => {
if (child.onClick) {
e.preventDefault();
child.onClick();
}
onItemClick();
}}
sx={{
py: 1.25,
pl: 5,
pr: 3,
minHeight: 44,
'&:hover': {
bgcolor: 'var(--fa-color-brand-100)',
},
}}
>
<ListItemText
primary={child.label}
primaryTypographyProps={{
fontWeight: 400,
fontSize: '0.9375rem',
color: 'text.secondary',
}}
/>
</ListItemButton>
))}
</List>
</Collapse>
</>
);
};
// ─── Component ─────────────────────────────────────────────────────────────── // ─── Component ───────────────────────────────────────────────────────────────
/** /**
@@ -215,13 +51,26 @@ const MobileCollapsible: React.FC<MobileCollapsibleProps> = ({ item, onItemClick
* *
* Responsive header with logo, navigation links, and optional CTA. * Responsive header with logo, navigation links, and optional CTA.
* Desktop shows links inline; mobile collapses to hamburger + drawer. * Desktop shows links inline; mobile collapses to hamburger + drawer.
* Items with `children` render as a dropdown (desktop) or collapsible
* section (mobile).
* *
* Maps to Figma "Main Nav" (14:108) desktop and "Mobile Header" * Maps to Figma "Main Nav" (14:108) desktop and "Mobile Header"
* (2391:41508) mobile patterns. * (2391:41508) mobile patterns.
* *
* Composes AppBar + Link + IconButton + Button + Divider + Drawer + Menu. * Composes AppBar + Link + IconButton + Button + Divider + Drawer.
*
* Usage:
* ```tsx
* <Navigation
* logo={<img src="/logo.svg" alt="Funeral Arranger" height={40} />}
* onLogoClick={() => navigate('/')}
* items={[
* { label: 'FAQ', href: '/faq' },
* { label: 'Contact Us', href: '/contact' },
* { label: 'Log in', href: '/login' },
* ]}
* ctaLabel="Start planning"
* onCtaClick={() => navigate('/arrange')}
* />
* ```
*/ */
export const Navigation = React.forwardRef<HTMLDivElement, NavigationProps>( export const Navigation = React.forwardRef<HTMLDivElement, NavigationProps>(
({ logo, onLogoClick, items = [], ctaLabel, onCtaClick, sx }, ref) => { ({ logo, onLogoClick, items = [], ctaLabel, onCtaClick, sx }, ref) => {
@@ -229,7 +78,6 @@ export const Navigation = React.forwardRef<HTMLDivElement, NavigationProps>(
const isMobile = useMediaQuery((theme: Theme) => theme.breakpoints.down('md')); const isMobile = useMediaQuery((theme: Theme) => theme.breakpoints.down('md'));
const handleDrawerToggle = () => setDrawerOpen((prev) => !prev); const handleDrawerToggle = () => setDrawerOpen((prev) => !prev);
const closeDrawer = () => setDrawerOpen(false);
return ( return (
<> <>
@@ -299,28 +147,24 @@ export const Navigation = React.forwardRef<HTMLDivElement, NavigationProps>(
aria-label="Main navigation" aria-label="Main navigation"
sx={{ display: 'flex', alignItems: 'center', gap: 3.5 }} sx={{ display: 'flex', alignItems: 'center', gap: 3.5 }}
> >
{items.map((item) => {items.map((item) => (
item.children && item.children.length > 0 ? ( <Link
<DesktopDropdown key={item.label} item={item} /> key={item.label}
) : ( href={item.href}
<Link onClick={item.onClick}
key={item.label} underline="hover"
href={item.href} sx={{
onClick={item.onClick} color: 'var(--fa-color-brand-900)',
underline="hover" fontWeight: 600,
sx={{ fontSize: '1rem',
color: 'var(--fa-color-brand-900)', '&:hover': {
fontWeight: 600, color: 'primary.main',
fontSize: '1rem', },
'&:hover': { }}
color: 'primary.main', >
}, {item.label}
}} </Link>
> ))}
{item.label}
</Link>
),
)}
{ctaLabel && ( {ctaLabel && (
<Button variant="contained" size="medium" onClick={onCtaClick}> <Button variant="contained" size="medium" onClick={onCtaClick}>
@@ -366,40 +210,36 @@ export const Navigation = React.forwardRef<HTMLDivElement, NavigationProps>(
{/* Nav items */} {/* Nav items */}
<List component="nav" aria-label="Main navigation"> <List component="nav" aria-label="Main navigation">
{items.map((item) => {items.map((item) => (
item.children && item.children.length > 0 ? ( <ListItemButton
<MobileCollapsible key={item.label} item={item} onItemClick={closeDrawer} /> key={item.label}
) : ( component="a"
<ListItemButton href={item.href}
key={item.label} onClick={(e: React.MouseEvent) => {
component="a" if (item.onClick) {
href={item.href} e.preventDefault();
onClick={(e: React.MouseEvent) => { item.onClick();
if (item.onClick) { }
e.preventDefault(); setDrawerOpen(false);
item.onClick(); }}
} sx={{
closeDrawer(); py: 1.5,
px: 3,
minHeight: 44,
'&:hover': {
bgcolor: 'var(--fa-color-brand-100)',
},
}}
>
<ListItemText
primary={item.label}
primaryTypographyProps={{
fontWeight: 500,
fontSize: '1rem',
}} }}
sx={{ />
py: 1.5, </ListItemButton>
px: 3, ))}
minHeight: 44,
'&:hover': {
bgcolor: 'var(--fa-color-brand-100)',
},
}}
>
<ListItemText
primary={item.label}
primaryTypographyProps={{
fontWeight: 500,
fontSize: '1rem',
}}
/>
</ListItemButton>
),
)}
</List> </List>
{ctaLabel && ( {ctaLabel && (
@@ -410,7 +250,7 @@ export const Navigation = React.forwardRef<HTMLDivElement, NavigationProps>(
fullWidth fullWidth
onClick={() => { onClick={() => {
if (onCtaClick) onCtaClick(); if (onCtaClick) onCtaClick();
closeDrawer(); setDrawerOpen(false);
}} }}
> >
{ctaLabel} {ctaLabel}

View File

@@ -40,16 +40,6 @@ const nav = (
<Navigation <Navigation
logo={<FALogo />} logo={<FALogo />}
items={[ items={[
{
label: 'Locations',
children: [
{ label: 'Melbourne', href: '/locations/melbourne' },
{ label: 'Brisbane', href: '/locations/brisbane' },
{ label: 'Sydney', href: '/locations/sydney' },
{ label: 'South Coast NSW', href: '/locations/south-coast-nsw' },
{ label: 'Central Coast NSW', href: '/locations/central-coast-nsw' },
],
},
{ label: 'FAQ', href: '/faq' }, { label: 'FAQ', href: '/faq' },
{ label: 'Contact Us', href: '/contact' }, { label: 'Contact Us', href: '/contact' },
{ label: 'Log in', href: '/login' }, { label: 'Log in', href: '/login' },

View File

@@ -186,8 +186,8 @@ export const HomePage = React.forwardRef<HTMLDivElement, HomePageProps>(
discoverMapSlot, discoverMapSlot,
onSelectFeaturedProvider, onSelectFeaturedProvider,
features = [], features = [],
featuresHeading = '4 Reasons to use Funeral Arranger', featuresHeading = 'How it works',
featuresBody, featuresBody = 'Search local funeral directors, compare transparent pricing, and personalise a plan — all in your own time. No pressure, no hidden costs.',
googleRating, googleRating,
googleReviewCount, googleReviewCount,
testimonials = [], testimonials = [],
@@ -241,28 +241,17 @@ export const HomePage = React.forwardRef<HTMLDivElement, HomePageProps>(
}} }}
> >
<Container <Container
maxWidth={false} maxWidth="md"
sx={{ sx={{
position: 'relative', position: 'relative',
zIndex: 1, zIndex: 1,
textAlign: 'center', textAlign: 'center',
maxWidth: 990,
pt: { xs: 10, md: 14 }, pt: { xs: 10, md: 14 },
pb: { xs: 3, md: 4 }, pb: { xs: 3, md: 4 },
}} }}
> >
<Typography <Typography
variant="body1" variant="display3"
sx={{
color: 'rgba(255,255,255,0.85)',
fontStyle: 'italic',
mb: 2,
}}
>
Trusted by thousands of families across Australia
</Typography>
<Typography
variant="display2"
component="h1" component="h1"
id="hero-heading" id="hero-heading"
tabIndex={-1} tabIndex={-1}
@@ -291,7 +280,13 @@ export const HomePage = React.forwardRef<HTMLDivElement, HomePageProps>(
}} }}
> >
<Box sx={{ width: '100%', maxWidth: finderSlot ? 500 : 520, mx: 'auto' }}> <Box sx={{ width: '100%', maxWidth: finderSlot ? 500 : 520, mx: 'auto' }}>
{finderSlot || <FuneralFinderV3 onSearch={onSearch} loading={searchLoading} />} {finderSlot || (
<FuneralFinderV3
heading="Find your local providers"
onSearch={onSearch}
loading={searchLoading}
/>
)}
</Box> </Box>
</Box> </Box>
</Box> </Box>
@@ -321,7 +316,7 @@ export const HomePage = React.forwardRef<HTMLDivElement, HomePageProps>(
}} }}
> >
<Typography <Typography
variant="display2" variant="display3"
component="h1" component="h1"
id="hero-heading" id="hero-heading"
tabIndex={-1} tabIndex={-1}
@@ -374,7 +369,13 @@ export const HomePage = React.forwardRef<HTMLDivElement, HomePageProps>(
}} }}
> >
<Box sx={{ maxWidth: 620, mx: 'auto' }}> <Box sx={{ maxWidth: 620, mx: 'auto' }}>
{finderSlot || <FuneralFinderV3 onSearch={onSearch} loading={searchLoading} />} {finderSlot || (
<FuneralFinderV3
heading="Find your local providers"
onSearch={onSearch}
loading={searchLoading}
/>
)}
</Box> </Box>
</Box> </Box>
)} )}
@@ -800,30 +801,21 @@ export const HomePage = React.forwardRef<HTMLDivElement, HomePageProps>(
> >
<Container maxWidth="lg"> <Container maxWidth="lg">
<Box sx={{ textAlign: 'center', mb: { xs: 5, md: 8 } }}> <Box sx={{ textAlign: 'center', mb: { xs: 5, md: 8 } }}>
<Typography
variant="overline"
component="div"
sx={{ color: 'var(--fa-color-brand-600)', mb: 1.5 }}
>
Why Use Funeral Arranger
</Typography>
<Typography <Typography
variant="display3" variant="display3"
component="h2" component="h2"
id="features-heading" id="features-heading"
sx={{ mb: featuresBody ? 2.5 : 0, color: 'text.primary' }} sx={{ mb: 2.5, color: 'text.primary' }}
> >
{featuresHeading} {featuresHeading}
</Typography> </Typography>
{featuresBody && ( <Typography
<Typography variant="body1"
variant="body1" color="text.secondary"
color="text.secondary" sx={{ maxWidth: 560, mx: 'auto', fontSize: { xs: '0.875rem', md: '1rem' } }}
sx={{ maxWidth: 560, mx: 'auto', fontSize: { xs: '0.875rem', md: '1rem' } }} >
> {featuresBody}
{featuresBody} </Typography>
</Typography>
)}
</Box> </Box>
<Box <Box
@@ -874,17 +866,6 @@ export const HomePage = React.forwardRef<HTMLDivElement, HomePageProps>(
}} }}
> >
<Container maxWidth="md"> <Container maxWidth="md">
<Typography
variant="overline"
component="div"
sx={{
textAlign: 'center',
color: 'var(--fa-color-brand-600)',
mb: 1.5,
}}
>
Funeral Arranger Reviews
</Typography>
<Typography <Typography
variant="display3" variant="display3"
component="h2" component="h2"
@@ -997,7 +978,7 @@ export const HomePage = React.forwardRef<HTMLDivElement, HomePageProps>(
> >
{ctaHeading} {ctaHeading}
</Typography> </Typography>
<Button variant="contained" size="medium" onClick={onCtaClick}> <Button variant="text" size="large" onClick={onCtaClick}>
{ctaButtonLabel} {ctaButtonLabel}
</Button> </Button>
</Container> </Container>

View File

@@ -42,16 +42,6 @@ const nav = (
<Navigation <Navigation
logo={<FALogo />} logo={<FALogo />}
items={[ items={[
{
label: 'Locations',
children: [
{ label: 'Melbourne', href: '/locations/melbourne' },
{ label: 'Brisbane', href: '/locations/brisbane' },
{ label: 'Sydney', href: '/locations/sydney' },
{ label: 'South Coast NSW', href: '/locations/south-coast-nsw' },
{ label: 'Central Coast NSW', href: '/locations/central-coast-nsw' },
],
},
{ label: 'FAQ', href: '/faq' }, { label: 'FAQ', href: '/faq' },
{ label: 'Contact Us', href: '/contact' }, { label: 'Contact Us', href: '/contact' },
{ label: 'Log in', href: '/login' }, { label: 'Log in', href: '/login' },

View File

@@ -38,16 +38,6 @@ const nav = (
<Navigation <Navigation
logo={<FALogo />} logo={<FALogo />}
items={[ items={[
{
label: 'Locations',
children: [
{ label: 'Melbourne', href: '/locations/melbourne' },
{ label: 'Brisbane', href: '/locations/brisbane' },
{ label: 'Sydney', href: '/locations/sydney' },
{ label: 'South Coast NSW', href: '/locations/south-coast-nsw' },
{ label: 'Central Coast NSW', href: '/locations/central-coast-nsw' },
],
},
{ label: 'FAQ', href: '/faq' }, { label: 'FAQ', href: '/faq' },
{ label: 'Contact Us', href: '/contact' }, { label: 'Contact Us', href: '/contact' },
{ label: 'Log in', href: '/login' }, { label: 'Log in', href: '/login' },
@@ -268,7 +258,7 @@ export const Default: Story = {
args: { args: {
navigation: nav, navigation: nav,
footer, footer,
heroImageUrl: assetUrl('/images/heroes/hero-couple.jpg'), heroImageUrl: assetUrl('/images/heroes/hero-3.png'),
heroHeading: 'Compare funeral director pricing near you and arrange with confidence', heroHeading: 'Compare funeral director pricing near you and arrange with confidence',
heroSubheading: 'Transparent pricing \u00B7 No hidden fees \u00B7 Arrange 24/7', heroSubheading: 'Transparent pricing \u00B7 No hidden fees \u00B7 Arrange 24/7',
stats: trustStats, stats: trustStats,

View File

@@ -39,16 +39,6 @@ const nav = (
<Navigation <Navigation
logo={<FALogo />} logo={<FALogo />}
items={[ items={[
{
label: 'Locations',
children: [
{ label: 'Melbourne', href: '/locations/melbourne' },
{ label: 'Brisbane', href: '/locations/brisbane' },
{ label: 'Sydney', href: '/locations/sydney' },
{ label: 'South Coast NSW', href: '/locations/south-coast-nsw' },
{ label: 'Central Coast NSW', href: '/locations/central-coast-nsw' },
],
},
{ label: 'FAQ', href: '/faq' }, { label: 'FAQ', href: '/faq' },
{ label: 'Contact Us', href: '/contact' }, { label: 'Contact Us', href: '/contact' },
{ label: 'Log in', href: '/login' }, { label: 'Log in', href: '/login' },