import { StoryObj, Meta } from "@storybook/react-vite"; import Card from "./card"; const content = "Enim aliquip excepteur veniam esse culpa. Et exercitation incididunt occaecat incididunt proident consectetur. Voluptate elit reprehenderit nulla reprehenderit excepteur tempor adipisicing officia eiusmod est id aute. Nisi do et nulla fugiat enim id pariatur ex. Culpa aliquip excepteur velit fugiat qui magna deserunt adipisicing dolore quis. Esse proident qui consectetur Lorem id fugiat elit amet proident enim deserunt dolore sit."; const meta: Meta = { title: "FP.React Components/Card", tags: ["stable", "autodocs"], component: Card, args: { children:

{content}

, classes: "shadow-sm rounded-lg", }, argTypes: { as: { control: "select", options: ["div", "article", "section", "aside"], description: "HTML element to render", }, interactive: { control: "boolean", description: "Enable keyboard navigation and button semantics", }, role: { control: "text", description: "ARIA role attribute", }, }, parameters: { docs: { description: { component: "A flexible, accessible card component with compound component pattern. Supports polymorphic rendering, interactive variants, and WCAG 2.1 AA compliance.", }, }, }, } as Meta; export default meta; type Story = StoryObj; export const CardComponent: Story = { args: {}, }; export const Multiple: Story = { args: { styles: { "--theme": "warm", }, }, render: (args) => (

Proident et amet aliqua excepteur sunt qui deserunt commodo tempor esse. Et aliqua nulla ea amet nisi consequat id adipisicing culpa ipsum minim voluptate est Lorem. Amet qui laboris incididunt commodo culpa aliqua veniam.

Proident et amet aliqua excepteur sunt qui deserunt commodo tempor esse. Et aliqua nulla ea amet nisi consequat id adipisicing culpa ipsum minim voluptate est Lorem. Amet qui laboris incididunt commodo culpa aliqua veniam.

Proident et amet aliqua excepteur sunt qui deserunt commodo tempor esse. Et aliqua nulla ea amet nisi consequat id adipisicing culpa ipsum minim voluptate est Lorem. Amet qui laboris incididunt commodo culpa aliqua veniam.

), } as Story; export const CardWithTitle: Story = { args: {}, render: (args) => ( Card Title

This card demonstrates the usage of the CardTitle component. It shows how a title can be added to a card for better organization and visual hierarchy.

), } as Story; export const FlexibleContent: Story = { args: { styles: { // '--card-bg': '#f0f0f0', }, }, render: (args) => (
Card Title

This card demonstrates the usage of the CardTitle component. It shows how a title can be added to a card for better organization and visual hierarchy.

Footer Content

Second Card Title

This card demonstrates the usage of the CardTitle component. It shows how a title can be added to a card for better organization and visual hierarchy.

This card demonstrates the usage of the CardTitle component. It shows how a title can be added to a card for better organization and visual hierarchy.

Footer Content

Random Image Second Card Title

This card demonstrates the usage of the CardTitle component. It shows how a title can be added to a card for better organization and visual hierarchy.

Footer Content

Random Image Second Card Title

This card demonstrates the usage of the CardTitle component. It shows how a title can be added to a card for better organization and visual hierarchy.

Footer Content

), } as Story; /** * Interactive Card - Demonstrates clickable card with keyboard navigation */ export const InteractiveCard: Story = { args: { interactive: true, "aria-label": "View product details", }, render: (args) => ( alert("Card clicked!")} style={{ cursor: "pointer" }} > Interactive Product Card

This card is fully interactive! Click anywhere or use your keyboard (Tab to focus, Enter or Space to activate) to trigger the action.

Try it: Tab to focus this card, then press Enter or Space.

Click to learn more →
), parameters: { docs: { description: { story: "Interactive cards support full keyboard navigation (Enter/Space keys) and automatically receive proper ARIA attributes for accessibility.", }, }, }, } as Story; /** * Accessible Card with ARIA - Demonstrates proper ARIA labeling */ export const AccessibleCard: Story = { render: () => ( Featured Product

This card uses aria-labelledby to connect the title with the card container, providing an accessible name for screen readers.

Screen readers will announce: "Featured Product, article"

), parameters: { docs: { description: { story: "Demonstrates best practices for accessible cards using aria-labelledby to provide context to assistive technologies.", }, }, }, } as Story; /** * Polymorphic Card - Shows different HTML elements */ export const PolymorphicElements: Story = { render: () => (
Article Card Renders as <article> element for standalone content Section Card Renders as <section> element for thematic grouping Aside Card Renders as <aside> element for tangential content
), parameters: { docs: { description: { story: "The Card component supports polymorphic rendering via the `as` prop, allowing you to use semantic HTML elements while maintaining consistent styling.", }, }, }, } as Story; /** * Custom Heading Levels - Demonstrates heading hierarchy */ export const CustomHeadingLevels: Story = { render: () => (
Level 1 Heading Main page title level Level 2 Heading Section title level Level 3 Heading (Default) Subsection title level - this is the default Level 4 Heading Component title level
), parameters: { docs: { description: { story: "Card.Title supports all heading levels (h1-h6) to maintain proper document outline and heading hierarchy.", }, }, }, } as Story; /** * CSS Variable Customization * * Demonstrates how to customize card appearance using the new standardized * CSS custom property naming convention. * * New variable naming patterns: * - Base properties: `--card-padding`, `--card-radius`, `--card-bg`, `--card-gap` * - Element-specific: `--card-header-*`, `--card-body-*`, `--card-footer-*` * - Full property names (no single-letter abbreviations) */ export const Customization: Story = { render: () => (
{/* Custom padding and spacing */}

Custom Padding & Spacing

Spacious Card

This card uses custom padding (3rem) and larger border radius (1rem).

{/* Compact card */}

Compact Card

Compact Card

This card uses minimal padding and smaller gaps for a compact layout.

{/* Custom header/footer styling */}

Element-Specific Customization (Header, Body, Footer)

Custom Header

This card demonstrates element-specific customization using the new scoped variables.

Header has custom blue background, body has custom padding, footer has custom gray background.

Custom Footer Content

Green Theme

Another example with green theme and custom element spacing.

Footer with light green background
{/* Dark theme card */}

Dark Theme Example

Dark Mode Card

This card demonstrates dark theme customization with all element-specific variables.

Styled with CSS custom properties
{/* Brand card */}

Brand Card (No Radius, Custom Colors)

Brand Card

This card uses brand colors and no border radius for a distinct look.

), parameters: { docs: { description: { story: ` ## Available CSS Variables ### Base Properties - \`--card-padding\`: Main card padding (default: 2rem) - \`--card-bg\`: Background color (default: #fff) - \`--card-radius\`: Border radius (default: calc(var(--card-padding) / 4)) - \`--card-display\`: Display property (default: flex) - \`--card-direction\`: Flex direction (default: column) - \`--card-gap\`: Gap between child elements (default: 1rem) ### Element-Specific Variables (NEW) #### Header - \`--card-header-padding\`: Header padding (default: 1rem 1.5rem) - \`--card-header-bg\`: Header background color (default: #f8f9fa) - \`--card-header-border-bottom\`: Header bottom border (default: 1px solid #dee2e6) #### Body - \`--card-body-padding\`: Body content padding (default: 1.5rem) #### Footer - \`--card-footer-padding\`: Footer padding (default: 1rem 1.5rem) - \`--card-footer-bg\`: Footer background color (default: #f8f9fa) - \`--card-footer-border-top\`: Footer top border (default: 1px solid #dee2e6) ### Migration from Old Names - ❌ \`--card-p\` → ✅ \`--card-padding\` ### Usage with Element Selectors Element-specific variables work with: - \`
\` or \`[data-card-header]\` - \`[data-card-body]\` - \`