import type { Meta, StoryObj } from "@storybook/react-vite"; import { within, expect } from "storybook/test"; import { Stack } from "./stack"; import "./stack.scss"; const meta: Meta = { title: "FP.React Components/Layout/Stack", component: Stack, tags: ["autodocs", "beta", "layout"], parameters: { docs: { description: { component: ` # Stack - Layout Primitive A simplified flexbox primitive for vertical or horizontal layouts with consistent gap spacing between children. ## Features - **Simple API**: Fewer props than Flex for common use cases - **Fluid Spacing**: Responsive gap using CSS clamp() - **Flexbox-Based**: Reliable cross-browser layout - **Polymorphic**: Render as any semantic HTML element - **Type-Safe**: Full TypeScript support ## When to Use - **Stack**: Simple vertical/horizontal layouts with gap spacing - **Flex**: Complex responsive layouts with advanced flex properties - **Box**: Padding/margin on containers (no gap between children) [View Full Documentation →](https://github.com/anthropics/fpkit/blob/main/packages/fpkit/src/components/stack/README.mdx) `, }, }, }, }; export default meta; type Story = StoryObj; /** * Default vertical Stack with medium gap. * Stack defaults to vertical direction with medium gap between children. */ export const Default: Story = { args: { gap: "md", children: ( <>
Item 1
Item 2
Item 3
), }, play: async ({ canvasElement, step }) => { const canvas = within(canvasElement); await step("Stack renders correctly", async () => { const item1 = canvas.getByText("Item 1"); expect(item1).toBeInTheDocument(); }); await step("Stack has correct classes", async () => { const stack = canvas.getByText("Item 1").parentElement; expect(stack).toHaveClass("stack"); expect(stack).toHaveClass("stack-vertical"); expect(stack).toHaveClass("stack-gap-md"); }); }, }; /** * Different gap sizes. * Demonstrates the unified spacing scale from xs to xl. */ export const GapSizes: Story = { render: () => (

Gap XS (4-8px)

Item
Item
Item

Gap SM (8-12px)

Item
Item
Item

Gap MD (12-18px)

Item
Item
Item

Gap LG (16-24px)

Item
Item
Item

Gap XL (24-32px)

Item
Item
Item
), }; /** * Horizontal Stack for button groups. * Use direction="horizontal" for side-by-side layouts. */ export const Horizontal: Story = { args: { direction: "horizontal", gap: "sm", children: ( <> ), }, }; /** * Centered vertical Stack. * Common pattern for hero sections or centered content. */ export const CenteredVertical: Story = { args: { gap: "lg", align: "center", justify: "center", styles: { minHeight: "400px", backgroundColor: "#f8f9fa", border: "2px dashed #ccc", }, children: ( <>

Welcome

Get started with our platform

), }, }; /** * Horizontal navigation Stack. * Demonstrates semantic nav element with horizontal layout. */ export const Navigation: Story = { args: { as: "nav", direction: "horizontal", gap: "md", align: "center", styles: { padding: "1rem", backgroundColor: "#f8f9fa", border: "1px solid #e0e0e0", }, children: ( <>
Logo
Home About Contact ), }, }; /** * Vertical content sections. * Common pattern for article or page layouts. */ export const ContentSections: Story = { args: { as: "article", gap: "xl", styles: { maxWidth: "48rem", margin: "0 auto", padding: "2rem", }, children: ( <>

Article Title

Published on December 3, 2025

This is the introduction paragraph with some meaningful content about the article topic.

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

Section Heading

More content goes here with proper spacing between sections using the Stack component.

), }, }; /** * Alignment variations. * Demonstrates different alignment options on cross-axis. */ export const Alignments: Story = { render: () => (

Align Start (default)

Short item
Medium item
Small

Align Center

Short item
Medium item
Small

Align End

Short item
Medium item
Small

Align Stretch

Stretched item (full width)
Stretched item (full width)
Stretched item (full width)
), }; /** * Justification variations. * Demonstrates different justification options on main-axis. */ export const Justifications: Story = { render: () => (

Justify Start (default)

Item 1
Item 2
Item 3

Justify Center

Item 1
Item 2
Item 3

Justify End

Item 1
Item 2
Item 3

Justify Between

Item 1
Item 2
Item 3
), }; /** * Wrapping horizontal Stack. * Items wrap to next line when exceeding container width. */ export const Wrapping: Story = { args: { direction: "horizontal", gap: "sm", wrap: "wrap", styles: { maxWidth: "400px", border: "2px dashed #ccc", padding: "1rem", }, children: ( <> {Array.from({ length: 10 }, (_, i) => (
Item {i + 1}
))} ), }, }; /** * Nested Stacks. * Demonstrates composing Stack components for complex layouts. */ export const NestedStacks: Story = { render: () => (

Dashboard

Card 1

Nested vertical Stack inside horizontal Stack

Card 2

Each card is an independent Stack

), }; /** * Form layout with Stack. * Common pattern for form field layouts. */ export const FormLayout: Story = { render: () => (

Sign Up Form

), };