Moved all 17 components from ui/ into atomic design tiers: atoms (Button, IconButton, Input, Textarea, Select, Checkbox, Radio, Switch, Badge, Tag, Chip, Tooltip) and molecules (Alert, Accordion, Card, Dialog, Popover). Updated all Storybook titles and cross-component imports. Changed Input icons to primary-dark and replaced palette token references with semantic tokens. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
258 lines
7.3 KiB
TypeScript
258 lines
7.3 KiB
TypeScript
import type { Meta, StoryObj } from '@storybook/react-vite'
|
|
import { ClipboardList, BookOpen, Info, ExternalLink } from 'lucide-react'
|
|
import { Card, CardHeader, CardTitle, CardDescription, CardContent, CardFooter } from './Card'
|
|
|
|
const meta: Meta<typeof Card> = {
|
|
title: 'Molecules/Card',
|
|
component: Card,
|
|
tags: ['autodocs'],
|
|
argTypes: {
|
|
variant: {
|
|
control: 'select',
|
|
options: ['surface', 'outlined', 'elevated', 'filled'],
|
|
},
|
|
},
|
|
decorators: [
|
|
(Story) => (
|
|
<div className="max-w-lg">
|
|
<Story />
|
|
</div>
|
|
),
|
|
],
|
|
}
|
|
|
|
export default meta
|
|
type Story = StoryObj<typeof meta>
|
|
|
|
export const Default: Story = {
|
|
render: () => (
|
|
<Card>
|
|
<CardHeader>
|
|
<CardTitle>Card title</CardTitle>
|
|
<CardDescription>A short description of the card content.</CardDescription>
|
|
</CardHeader>
|
|
<CardContent>
|
|
<p className="text-body text-text">
|
|
This is the card body. It can contain any content — text, lists, forms, or other
|
|
components.
|
|
</p>
|
|
</CardContent>
|
|
</Card>
|
|
),
|
|
}
|
|
|
|
// --- Variants ---
|
|
|
|
export const Surface: Story = {
|
|
render: () => (
|
|
<Card variant="surface">
|
|
<CardHeader>
|
|
<CardTitle>Surface</CardTitle>
|
|
</CardHeader>
|
|
<CardContent>
|
|
<p className="text-body text-text">Default variant with border and subtle shadow.</p>
|
|
</CardContent>
|
|
</Card>
|
|
),
|
|
}
|
|
|
|
export const Outlined: Story = {
|
|
render: () => (
|
|
<Card variant="outlined">
|
|
<CardHeader>
|
|
<CardTitle>Outlined</CardTitle>
|
|
</CardHeader>
|
|
<CardContent>
|
|
<p className="text-body text-text">Border only, no shadow. Good for less prominent cards.</p>
|
|
</CardContent>
|
|
</Card>
|
|
),
|
|
}
|
|
|
|
export const Elevated: Story = {
|
|
render: () => (
|
|
<Card variant="elevated">
|
|
<CardHeader>
|
|
<CardTitle>Elevated</CardTitle>
|
|
</CardHeader>
|
|
<CardContent>
|
|
<p className="text-body text-text">Shadow only, no border. Creates a floating effect.</p>
|
|
</CardContent>
|
|
</Card>
|
|
),
|
|
}
|
|
|
|
export const Filled: Story = {
|
|
render: () => (
|
|
<Card variant="filled">
|
|
<CardHeader>
|
|
<CardTitle>Professional pathway</CardTitle>
|
|
<CardDescription className="text-white/70">
|
|
Track your progress through each stage.
|
|
</CardDescription>
|
|
</CardHeader>
|
|
<CardContent>
|
|
<p className="text-body text-white/90">
|
|
Dark filled variant for featured or highlighted content sections.
|
|
</p>
|
|
</CardContent>
|
|
</Card>
|
|
),
|
|
}
|
|
|
|
// --- With header action ---
|
|
|
|
export const WithHeaderAction: Story = {
|
|
render: () => (
|
|
<Card>
|
|
<CardHeader
|
|
action={
|
|
<button className="rounded-full p-1 text-text-secondary hover:bg-primary/5">
|
|
<Info className="size-5" />
|
|
</button>
|
|
}
|
|
>
|
|
<div className="flex items-center gap-2">
|
|
<ClipboardList className="size-5 text-primary-dark" />
|
|
<CardTitle>Steps to be taken</CardTitle>
|
|
</div>
|
|
</CardHeader>
|
|
<CardContent>
|
|
<ul className="divide-y divide-border">
|
|
<li className="flex items-center justify-between py-3 text-body text-text">
|
|
Apply and verify WWCC
|
|
<span className="text-text-secondary">›</span>
|
|
</li>
|
|
<li className="flex items-center justify-between py-3 text-body text-text">
|
|
Fill a Registration Form
|
|
<span className="text-text-secondary">›</span>
|
|
</li>
|
|
<li className="flex items-center justify-between py-3 text-body text-text">
|
|
Complete compliance modules
|
|
<span className="text-text-secondary">›</span>
|
|
</li>
|
|
</ul>
|
|
</CardContent>
|
|
</Card>
|
|
),
|
|
}
|
|
|
|
// --- With footer ---
|
|
|
|
export const WithFooter: Story = {
|
|
render: () => (
|
|
<Card>
|
|
<CardHeader>
|
|
<CardTitle>Mandatory Training Reminders</CardTitle>
|
|
<CardDescription>
|
|
Please consult the training hub for role-specific training requirements.
|
|
</CardDescription>
|
|
</CardHeader>
|
|
<CardContent>
|
|
<div className="flex items-center justify-between rounded-lg bg-bg px-3 py-2 text-small">
|
|
<span className="text-text">Aboriginal Cultural Education</span>
|
|
<span className="font-bold text-success">Certified</span>
|
|
</div>
|
|
</CardContent>
|
|
<CardFooter>
|
|
<button className="inline-flex items-center gap-1.5 rounded-lg border border-primary-dark px-3 py-1.5 text-small font-bold text-primary-dark hover:bg-primary/5">
|
|
<ExternalLink className="size-3.5" />
|
|
Go to myPL
|
|
</button>
|
|
</CardFooter>
|
|
</Card>
|
|
),
|
|
}
|
|
|
|
// --- Minimal ---
|
|
|
|
export const ContentOnly: Story = {
|
|
render: () => (
|
|
<Card>
|
|
<CardContent>
|
|
<p className="text-body text-text">
|
|
A card with just content — no header or footer. Useful as a simple container.
|
|
</p>
|
|
</CardContent>
|
|
</Card>
|
|
),
|
|
}
|
|
|
|
// --- Related information ---
|
|
|
|
export const RelatedInformation: Story = {
|
|
render: () => (
|
|
<Card>
|
|
<CardHeader
|
|
action={
|
|
<button className="rounded-full p-1 text-text-secondary hover:bg-primary/5">
|
|
<Info className="size-5" />
|
|
</button>
|
|
}
|
|
>
|
|
<div className="flex items-center gap-2">
|
|
<BookOpen className="size-5 text-primary-dark" />
|
|
<CardTitle>Related information</CardTitle>
|
|
</div>
|
|
</CardHeader>
|
|
<CardContent className="pt-0">
|
|
<ul className="divide-y divide-border">
|
|
<li className="flex items-center justify-between py-3 text-body text-text">
|
|
Visit the Beginning Teacher Information Hub
|
|
<span className="text-text-secondary">›</span>
|
|
</li>
|
|
<li className="flex items-center justify-between py-3 text-body text-text">
|
|
Apply for a role with DoE
|
|
<span className="text-text-secondary">›</span>
|
|
</li>
|
|
<li className="flex items-center justify-between py-3 text-body text-text">
|
|
Start your accreditation journey
|
|
<span className="text-text-secondary">›</span>
|
|
</li>
|
|
</ul>
|
|
</CardContent>
|
|
</Card>
|
|
),
|
|
}
|
|
|
|
// --- All variants ---
|
|
|
|
export const AllVariants: Story = {
|
|
render: () => (
|
|
<div className="flex flex-col gap-6">
|
|
<Card variant="surface">
|
|
<CardHeader>
|
|
<CardTitle>Surface</CardTitle>
|
|
</CardHeader>
|
|
<CardContent>
|
|
<p className="text-small text-text-secondary">Border + subtle shadow</p>
|
|
</CardContent>
|
|
</Card>
|
|
<Card variant="outlined">
|
|
<CardHeader>
|
|
<CardTitle>Outlined</CardTitle>
|
|
</CardHeader>
|
|
<CardContent>
|
|
<p className="text-small text-text-secondary">Border only</p>
|
|
</CardContent>
|
|
</Card>
|
|
<Card variant="elevated">
|
|
<CardHeader>
|
|
<CardTitle>Elevated</CardTitle>
|
|
</CardHeader>
|
|
<CardContent>
|
|
<p className="text-small text-text-secondary">Shadow only</p>
|
|
</CardContent>
|
|
</Card>
|
|
<Card variant="filled">
|
|
<CardHeader>
|
|
<CardTitle>Filled</CardTitle>
|
|
</CardHeader>
|
|
<CardContent>
|
|
<p className="text-small text-white/70">Dark background, white text</p>
|
|
</CardContent>
|
|
</Card>
|
|
</div>
|
|
),
|
|
}
|