import { useState } from 'react'; import type { Meta, StoryObj } from '@storybook/react'; import { Card } from './Card'; import { Typography } from '../Typography'; import { Button } from '../Button'; import Box from '@mui/material/Box'; const meta: Meta = { title: 'Atoms/Card', component: Card, tags: ['autodocs'], parameters: { layout: 'centered', }, argTypes: { variant: { control: 'select', options: ['elevated', 'outlined'], description: 'Visual style variant', table: { defaultValue: { summary: 'elevated' } }, }, interactive: { control: 'boolean', description: 'Adds hover background fill, shadow lift, and pointer cursor', table: { defaultValue: { summary: 'false' } }, }, selected: { control: 'boolean', description: 'Highlights the card as selected — brand border + warm background', table: { defaultValue: { summary: 'false' } }, }, padding: { control: 'select', options: ['default', 'compact', 'none'], description: 'Padding preset', table: { defaultValue: { summary: 'default' } }, }, }, }; export default meta; type Story = StoryObj; // ─── Default ──────────────────────────────────────────────────────────────── /** Default card — elevated with standard padding */ export const Default: Story = { args: { children: ( <> Funeral package A comprehensive service including chapel ceremony, transport, and preparation. Suitable for families seeking a traditional farewell. ), }, decorators: [ (Story) => (
), ], }; // ─── Variants ─────────────────────────────────────────────────────────────── /** Both visual variants side by side */ export const Variants: Story = { render: () => (
Elevated Uses shadow for depth. Default variant for most content cards. Outlined Uses a subtle border. Good for less prominent or grouped content.
), }; // ─── Interactive ──────────────────────────────────────────────────────────── /** Interactive cards with hover background fill and shadow lift */ export const Interactive: Story = { render: () => (
alert('Card clicked')}> Elevated + Interactive Hover to see the background fill and shadow lift. alert('Card clicked')} > Outlined + Interactive Outlined cards get a subtle background fill on hover.
), }; // ─── Selected ─────────────────────────────────────────────────────────────── /** Selected state — brand border + warm background tint */ export const Selected: Story = { render: () => (
Not selected Standard outlined card in its resting state. Selected Brand border and warm background tint show this is the active choice.
), }; // ─── Option Select Pattern ────────────────────────────────────────────────── /** * Interactive option selection matching the FA 1.0 "ListItemPurchaseOption" pattern. * Click a card to select it. Matches the Figma states: * inactive → hover (bg fill) → active (brand border + warm bg). */ export const OptionSelect: Story = { name: 'Option Select', render: function OptionSelectDemo() { const [selectedId, setSelectedId] = useState('chapel'); const options = [ { id: 'chapel', title: 'Chapel service', desc: 'Traditional ceremony in our heritage-listed chapel, seating up to 120 guests.', }, { id: 'graveside', title: 'Graveside service', desc: 'An intimate outdoor farewell at the final resting place.', }, { id: 'memorial', title: 'Memorial service', desc: 'A celebration of life gathering at a venue of your choosing.', }, ]; return (
Choose your service type {options.map((option) => ( setSelectedId(option.id)} role="radio" aria-checked={selectedId === option.id} > {option.title} {option.desc} ))}
); }, }; // ─── Multi-Select Pattern ─────────────────────────────────────────────────── /** * Multi-select variant — click to toggle multiple cards. * Useful for add-on services, package inclusions, etc. */ export const MultiSelect: Story = { name: 'Multi-Select', render: function MultiSelectDemo() { const [selected, setSelected] = useState>(new Set(['flowers'])); const addOns = [ { id: 'flowers', title: 'Floral arrangements', desc: 'Custom flowers for the service' }, { id: 'catering', title: 'Catering', desc: 'Light refreshments after the service' }, { id: 'music', title: 'Live musician', desc: 'Solo musician for the ceremony' }, { id: 'printing', title: 'Memorial printing', desc: 'Order of service booklets' }, ]; const toggle = (id: string) => { setSelected((prev) => { const next = new Set(prev); if (next.has(id)) next.delete(id); else next.add(id); return next; }); }; return (
Select add-ons Choose as many as you like
{addOns.map((item) => ( toggle(item.id)} role="checkbox" aria-checked={selected.has(item.id)} > {item.title} {item.desc} ))}
); }, }; // ─── On Different Backgrounds ─────────────────────────────────────────────── /** * Demonstrates how cards adapt to different surface colours. * Elevated cards stand out via shadow on any surface. * Outlined cards use borders on white, contrast on grey. */ export const OnDifferentBackgrounds: Story = { name: 'On Different Backgrounds', render: () => (
{/* White background */}
On white surface
Elevated Shadow defines edges Outlined Border defines edges
{/* Grey background */}
On grey surface
Elevated White card + shadow on grey Outlined Contrast + border on grey
), }; // ─── Padding Presets ──────────────────────────────────────────────────────── /** All three padding options */ export const PaddingPresets: Story = { name: 'Padding Presets', render: () => (
Default (24px) Standard spacing for desktop cards. Compact (16px) Tighter spacing for mobile or dense layouts. None (manual) Full control — add your own padding.
), }; // ─── Price Card Preview ───────────────────────────────────────────────────── /** * Preview of how Card will be used in the PriceCard molecule. * Demonstrates realistic content composition with FA typography and brand colours. */ export const PriceCardPreview: Story = { name: 'Price Card Preview', render: () => (
Essential $3,200 A respectful and simple service with chapel ceremony, transport, and professional preparation.
), }; // ─── With Image ───────────────────────────────────────────────────────────── /** Card with full-bleed image using padding="none" */ export const WithImage: Story = { name: 'With Image (No Padding)', render: () => (
Image placeholder Parsons Chapel Our heritage-listed chapel seats up to 120 guests and features modern audio-visual facilities.
), }; // ─── Rich Content ─────────────────────────────────────────────────────────── /** Card with rich nested content to verify layout flexibility */ export const RichContent: Story = { name: 'Rich Content', render: () => (
Package details Premium farewell
  • Chapel ceremony (up to 120 guests)
  • Premium timber casket
  • Transport within 50km
  • Professional preparation
  • ), };