From 2b39f43264a99eb8259bc0e467184fb7452a250c Mon Sep 17 00:00:00 2001 From: Richie Date: Thu, 23 Apr 2026 10:16:04 +1000 Subject: [PATCH] Promote HelpBar to a shared molecule MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Lifts HelpBar out of WizardLayout's internal scope into src/components/molecules/HelpBar/ so both WizardLayout and pages that bypass WizardLayout's chrome (currently: ProvidersStep's mobile map-first branch) render an identical sticky-footer. Before: WizardLayout had an internal HelpBar with the right styling (sticky, responsive px, phone format helper); ProvidersStep's mobile-map branch hand-rewrote the footer inline and had drifted — missing position: sticky, missing the md:4 responsive px, hard-coded phone number bypassing the prop default. This consolidates both to one source of truth. Props: `phone?` (defaults to FA's support number, spaces preserved in label, stripped in tel href) + `sx?` for caller chrome overrides. Two Storybook stories (Default, CustomNumber). Verified: footer text / height / sticky position identical between mobile-list (WizardLayout) and mobile-map (direct HelpBar). Co-Authored-By: Claude Opus 4.7 (1M context) --- .../molecules/HelpBar/HelpBar.stories.tsx | 32 ++++++++++ src/components/molecules/HelpBar/HelpBar.tsx | 64 +++++++++++++++++++ src/components/molecules/HelpBar/index.ts | 1 + .../pages/ProvidersStep/ProvidersStep.tsx | 26 ++------ .../templates/WizardLayout/WizardLayout.tsx | 30 +-------- 5 files changed, 102 insertions(+), 51 deletions(-) create mode 100644 src/components/molecules/HelpBar/HelpBar.stories.tsx create mode 100644 src/components/molecules/HelpBar/HelpBar.tsx create mode 100644 src/components/molecules/HelpBar/index.ts diff --git a/src/components/molecules/HelpBar/HelpBar.stories.tsx b/src/components/molecules/HelpBar/HelpBar.stories.tsx new file mode 100644 index 0000000..977fc9b --- /dev/null +++ b/src/components/molecules/HelpBar/HelpBar.stories.tsx @@ -0,0 +1,32 @@ +import type { Meta, StoryObj } from '@storybook/react'; +import Box from '@mui/material/Box'; +import { HelpBar } from './HelpBar'; + +const meta: Meta = { + title: 'Molecules/HelpBar', + component: HelpBar, + tags: ['autodocs'], + parameters: { layout: 'fullscreen' }, + decorators: [ + (Story) => ( + // Fake page content so the sticky footer has something to sit under. + + + Page content scrolls above the help bar. + + + + ), + ], +}; + +export default meta; +type Story = StoryObj; + +/** Default — uses FA's standard support number. */ +export const Default: Story = {}; + +/** Custom number — spaces preserved in the label, stripped in the tel link. */ +export const CustomNumber: Story = { + args: { phone: '1300 000 000' }, +}; diff --git a/src/components/molecules/HelpBar/HelpBar.tsx b/src/components/molecules/HelpBar/HelpBar.tsx new file mode 100644 index 0000000..74666bb --- /dev/null +++ b/src/components/molecules/HelpBar/HelpBar.tsx @@ -0,0 +1,64 @@ +import React from 'react'; +import Box from '@mui/material/Box'; +import PhoneIcon from '@mui/icons-material/Phone'; +import type { SxProps, Theme } from '@mui/material/styles'; +import { Typography } from '../../atoms/Typography'; +import { Link } from '../../atoms/Link'; + +// ─── Types ────────────────────────────────────────────────────────────────── + +/** Props for the FA HelpBar molecule */ +export interface HelpBarProps { + /** Phone number shown in the bar. Spaces preserved in the label, + * stripped in the `tel:` href. Defaults to FA's support number. */ + phone?: string; + /** MUI sx prop — merged onto the default footer chrome. */ + sx?: SxProps; +} + +// ─── Component ────────────────────────────────────────────────────────────── + +/** + * Sticky help footer used at the bottom of every wizard page. Shows a + * phone-icon prefix + "Need help? Call us on" + the support number as a + * tel-link. White fill, top border, sticky to the viewport bottom. + * + * Used by `WizardLayout` (for all variants that don't set `hideHelpBar`) + * and by pages that bypass WizardLayout's chrome (e.g. the mobile-map-first + * layout on `ProvidersStep`). Promoted from a WizardLayout-internal + * component so both sources render an identical footer — preventing drift + * if the phone number or styling ever changes. + */ +export const HelpBar = React.forwardRef( + ({ phone = '1800 987 888', sx }, ref) => ( + + + + Need help? Call us on{' '} + + {phone} + + + + ), +); + +HelpBar.displayName = 'HelpBar'; +export default HelpBar; diff --git a/src/components/molecules/HelpBar/index.ts b/src/components/molecules/HelpBar/index.ts new file mode 100644 index 0000000..74d3cb1 --- /dev/null +++ b/src/components/molecules/HelpBar/index.ts @@ -0,0 +1 @@ +export { HelpBar, type HelpBarProps } from './HelpBar'; diff --git a/src/components/pages/ProvidersStep/ProvidersStep.tsx b/src/components/pages/ProvidersStep/ProvidersStep.tsx index e2c1918..3166023 100644 --- a/src/components/pages/ProvidersStep/ProvidersStep.tsx +++ b/src/components/pages/ProvidersStep/ProvidersStep.tsx @@ -13,7 +13,6 @@ import useMediaQuery from '@mui/material/useMediaQuery'; import SwapVertIcon from '@mui/icons-material/SwapVert'; import ViewListOutlinedIcon from '@mui/icons-material/ViewListOutlined'; import MapOutlinedIcon from '@mui/icons-material/MapOutlined'; -import PhoneIcon from '@mui/icons-material/Phone'; import type { SxProps, Theme } from '@mui/material/styles'; import { useTheme } from '@mui/material/styles'; import { WizardLayout } from '../../templates/WizardLayout'; @@ -21,6 +20,7 @@ import { ProviderCard } from '../../molecules/ProviderCard'; import { FilterPanel } from '../../molecules/FilterPanel'; import { MapProviderDrawer } from '../../molecules/MapProviderDrawer'; import { LocationSearchInput } from '../../molecules/LocationSearchInput'; +import { HelpBar } from '../../molecules/HelpBar'; import { ProviderMap, type ProviderMapActiveState, @@ -28,7 +28,6 @@ import { } from '../../organisms/ProviderMap'; import { Button } from '../../atoms/Button'; import { Chip } from '../../atoms/Chip'; -import { Link } from '../../atoms/Link'; import { Switch } from '../../atoms/Switch'; import { Typography } from '../../atoms/Typography'; import { Divider } from '../../atoms/Divider'; @@ -673,26 +672,9 @@ export const ProvidersStep: React.FC = ({ /> - {/* Sticky help bar (matches WizardLayout) */} - - - - Need help? Call us on{' '} - - 1800 987 888 - - - + {/* Sticky help bar — shared HelpBar molecule so this footer stays + identical to WizardLayout's (which we bypass in this branch). */} + ); } diff --git a/src/components/templates/WizardLayout/WizardLayout.tsx b/src/components/templates/WizardLayout/WizardLayout.tsx index c20943f..c0976cc 100644 --- a/src/components/templates/WizardLayout/WizardLayout.tsx +++ b/src/components/templates/WizardLayout/WizardLayout.tsx @@ -2,10 +2,9 @@ import React from 'react'; import Box from '@mui/material/Box'; import Container from '@mui/material/Container'; import ArrowBackIcon from '@mui/icons-material/ArrowBack'; -import PhoneIcon from '@mui/icons-material/Phone'; import type { SxProps, Theme } from '@mui/material/styles'; import { Link } from '../../atoms/Link'; -import { Typography } from '../../atoms/Typography'; +import { HelpBar } from '../../molecules/HelpBar'; // ─── Types ─────────────────────────────────────────────────────────────────── @@ -51,33 +50,6 @@ export interface WizardLayoutProps { sx?: SxProps; } -// ─── Help bar ──────────────────────────────────────────────────────────────── - -const HelpBar: React.FC<{ phone: string }> = ({ phone }) => ( - - - - Need help? Call us on{' '} - - {phone} - - - -); - // ─── Back link ─────────────────────────────────────────────────────────────── const BackLink: React.FC<{ label: string; onClick?: () => void }> = ({ label, onClick }) => (