- CompareBar: add Mobile and MobileSingle stories (viewport: mobile1) so the xs-only collapse / auto-peek behaviour is discoverable in Storybook without setting up a live basket. - PackageDetail InCart story description updated to match the final toggle pattern (was stale from the earlier inert-pill attempt). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
197 lines
6.1 KiB
TypeScript
197 lines
6.1 KiB
TypeScript
import { useState } from 'react';
|
|
import type { Meta, StoryObj } from '@storybook/react';
|
|
import Box from '@mui/material/Box';
|
|
import { CompareBar } from './CompareBar';
|
|
import type { CompareBarPackage } from './CompareBar';
|
|
import { Button } from '../../atoms/Button';
|
|
import { Typography } from '../../atoms/Typography';
|
|
|
|
const samplePackages: CompareBarPackage[] = [
|
|
{ id: '1', name: 'Everyday Funeral Package', providerName: 'Wollongong City Funerals' },
|
|
{ id: '2', name: 'Traditional Cremation Service', providerName: 'Mackay Family Funerals' },
|
|
{ id: '3', name: 'Essential Burial Package', providerName: 'Inglewood Chapel' },
|
|
];
|
|
|
|
const meta: Meta<typeof CompareBar> = {
|
|
title: 'Molecules/CompareBar',
|
|
component: CompareBar,
|
|
tags: ['autodocs'],
|
|
parameters: {
|
|
layout: 'fullscreen',
|
|
},
|
|
decorators: [
|
|
(Story) => (
|
|
<Box sx={{ minHeight: '100vh', p: 4, bgcolor: 'var(--fa-color-surface-subtle)' }}>
|
|
<Typography variant="body2" color="text.secondary" sx={{ mb: 2 }}>
|
|
The compare bar floats at the bottom of the viewport.
|
|
</Typography>
|
|
<Story />
|
|
</Box>
|
|
),
|
|
],
|
|
};
|
|
|
|
export default meta;
|
|
type Story = StoryObj<typeof CompareBar>;
|
|
|
|
// --- Default (2 packages) ---------------------------------------------------
|
|
|
|
/** Two packages selected — "2 packages ready to compare" */
|
|
export const Default: Story = {
|
|
args: {
|
|
packages: samplePackages.slice(0, 2),
|
|
onCompare: () => alert('Compare clicked'),
|
|
},
|
|
};
|
|
|
|
// --- Single Package ----------------------------------------------------------
|
|
|
|
/** One package — "Add another package to compare", CTA disabled */
|
|
export const SinglePackage: Story = {
|
|
args: {
|
|
packages: samplePackages.slice(0, 1),
|
|
onCompare: () => alert('Compare clicked'),
|
|
},
|
|
};
|
|
|
|
// --- Three Packages (Maximum) ------------------------------------------------
|
|
|
|
/** Maximum 3 packages */
|
|
export const ThreePackages: Story = {
|
|
args: {
|
|
packages: samplePackages,
|
|
onCompare: () => alert('Compare clicked'),
|
|
},
|
|
};
|
|
|
|
// --- With Error --------------------------------------------------------------
|
|
|
|
/** Error message when user tries to add a 4th package */
|
|
export const WithError: Story = {
|
|
args: {
|
|
packages: samplePackages,
|
|
onCompare: () => alert('Compare clicked'),
|
|
error: 'Maximum 3 packages',
|
|
},
|
|
};
|
|
|
|
// --- Empty (Hidden) ----------------------------------------------------------
|
|
|
|
/** No packages — bar is hidden */
|
|
export const Empty: Story = {
|
|
args: {
|
|
packages: [],
|
|
onCompare: () => {},
|
|
},
|
|
};
|
|
|
|
// --- Mobile ------------------------------------------------------------------
|
|
|
|
/** Mobile viewport — expanded by default, with a grey-filled right-chevron
|
|
* on the right of the pill. Tap the chevron to retract the pill to the
|
|
* right corner (the middle content animates to width:0, so the pill
|
|
* visually shrinks as one unit rather than swapping into a separate mini
|
|
* pill). Tap the left-chevron on the collapsed pill to expand. On add
|
|
* while collapsed, the full bar auto-peeks for 3s, then re-collapses. */
|
|
export const Mobile: Story = {
|
|
args: {
|
|
packages: samplePackages.slice(0, 2),
|
|
onCompare: () => alert('Compare clicked'),
|
|
},
|
|
parameters: {
|
|
viewport: { defaultViewport: 'mobile1' },
|
|
},
|
|
};
|
|
|
|
/** Mobile — single package state. Same behaviour as `Mobile`, Compare
|
|
* CTA disabled ("Add another to compare"). */
|
|
export const MobileSingle: Story = {
|
|
args: {
|
|
packages: samplePackages.slice(0, 1),
|
|
onCompare: () => alert('Compare clicked'),
|
|
},
|
|
parameters: {
|
|
viewport: { defaultViewport: 'mobile1' },
|
|
},
|
|
};
|
|
|
|
// --- Interactive Demo --------------------------------------------------------
|
|
|
|
/** Interactive demo — add packages and see the bar update */
|
|
export const Interactive: Story = {
|
|
render: () => {
|
|
const [selected, setSelected] = useState<CompareBarPackage[]>([]);
|
|
const [error, setError] = useState<string>();
|
|
|
|
const allPackages = [
|
|
...samplePackages,
|
|
{ id: '4', name: 'Catholic Service', providerName: "St Mary's Funeral Services" },
|
|
];
|
|
|
|
const handleToggle = (pkg: CompareBarPackage) => {
|
|
const isSelected = selected.some((s) => s.id === pkg.id);
|
|
if (isSelected) {
|
|
setSelected(selected.filter((s) => s.id !== pkg.id));
|
|
setError(undefined);
|
|
} else {
|
|
if (selected.length >= 3) {
|
|
setError('Maximum 3 packages');
|
|
setTimeout(() => setError(undefined), 3000);
|
|
return;
|
|
}
|
|
setSelected([...selected, pkg]);
|
|
setError(undefined);
|
|
}
|
|
};
|
|
|
|
return (
|
|
<Box sx={{ pb: 12 }}>
|
|
<Typography variant="h4" sx={{ mb: 3 }}>
|
|
Select packages to compare
|
|
</Typography>
|
|
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 1.5 }}>
|
|
{allPackages.map((pkg) => {
|
|
const isSelected = selected.some((s) => s.id === pkg.id);
|
|
return (
|
|
<Box
|
|
key={pkg.id}
|
|
sx={{
|
|
display: 'flex',
|
|
alignItems: 'center',
|
|
justifyContent: 'space-between',
|
|
p: 2,
|
|
border: '1px solid',
|
|
borderColor: isSelected ? 'primary.main' : 'divider',
|
|
borderRadius: 'var(--fa-card-border-radius-default)',
|
|
bgcolor: isSelected ? 'var(--fa-color-surface-warm)' : 'background.paper',
|
|
}}
|
|
>
|
|
<Box>
|
|
<Typography variant="label">{pkg.name}</Typography>
|
|
<Typography variant="body2" color="text.secondary">
|
|
{pkg.providerName}
|
|
</Typography>
|
|
</Box>
|
|
<Button
|
|
variant={isSelected ? 'outlined' : 'soft'}
|
|
color="secondary"
|
|
size="small"
|
|
onClick={() => handleToggle(pkg)}
|
|
>
|
|
{isSelected ? 'Remove' : 'Compare'}
|
|
</Button>
|
|
</Box>
|
|
);
|
|
})}
|
|
</Box>
|
|
|
|
<CompareBar
|
|
packages={selected}
|
|
onCompare={() => alert(`Comparing: ${selected.map((s) => s.name).join(', ')}`)}
|
|
error={error}
|
|
/>
|
|
</Box>
|
|
);
|
|
},
|
|
};
|