import type { Meta, StoryObj } from "@storybook/react-vite"; import { within, expect } from "storybook/test"; import { Row } from "../row/row"; import { Col } from "./col"; const meta: Meta = { title: "FP.React Components/Layout/Col", component: Col, tags: ["autodocs", "beta", "layout"], parameters: { docs: { description: { component: "Col provides column elements for use within Row containers. Maps React props (span, offset, order, auto) to column utility classes without a base class. Use with Row component for responsive 12-column layouts.", }, }, }, argTypes: { span: { control: "select", options: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, "flex"], description: "Column span (1-12 columns) or 'flex' for flex-grow behavior", }, offset: { control: "select", options: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11], description: "Column offset (0-11 columns)", }, order: { control: "select", options: ["first", "last", 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], description: "Column visual order", }, auto: { control: "boolean", description: "Auto-width column (content-based)", }, as: { control: "select", options: ["div", "section", "article", "li"], description: "Element type to render", }, }, }; export default meta; type Story = StoryObj; const colStyle = { padding: "1rem", background: "#e0e7ff", border: "1px solid #6366f1", borderRadius: "0.25rem", textAlign: "center" as const, }; /** * Basic Columns - Demonstrates all column span sizes (1-12). * Shows the full range of column widths available. */ export const BasicColumns: Story = { render: () => (
col-12 (100%) col-6 (50%) col-6 (50%) col-4 (33.33%) col-4 (33.33%) col-4 (33.33%) col-3 col-3 col-3 col-3 col-2 col-2 col-2 col-2 col-2 col-2 {[...Array(12)].map((_, i) => ( 1 ))}
), play: async ({ canvasElement, step }) => { const canvas = within(canvasElement); await step("All column sizes render correctly", async () => { expect(canvas.getByText("col-12 (100%)")).toBeInTheDocument(); expect(canvas.getByText("col-6 (50%)")).toBeInTheDocument(); expect(canvas.getByText("col-4 (33.33%)")).toBeInTheDocument(); }); await step("Column classes are applied", async () => { const col12 = canvasElement.querySelector(".col-12"); expect(col12).toBeInTheDocument(); const col6Elements = canvasElement.querySelectorAll(".col-6"); expect(col6Elements).toHaveLength(2); }); }, }; /** * Column Offsets - Demonstrates offset positioning. * Shows how offset prop pushes columns to the right. */ export const ColumnOffsets: Story = { render: () => (
col-6 offset-3 (Centered) col-4 offset-4 (Centered) col-3 offset-0 col-3 offset-6 offset-2 offset-2 offset-2
), play: async ({ canvasElement, step }) => { await step("Offset classes are applied correctly", async () => { const offset3 = canvasElement.querySelector(".col-offset-3"); expect(offset3).toBeInTheDocument(); const offset4 = canvasElement.querySelector(".col-offset-4"); expect(offset4).toBeInTheDocument(); }); }, }; /** * Column Order - Demonstrates visual reordering with flexbox order. * Shows how order prop changes visual position without changing DOM order. */ export const ColumnOrder: Story = { render: () => (
DOM 1st, Visual 3rd DOM 2nd, Visual 1st DOM 3rd, Visual 2nd DOM 1st, order-last DOM 2nd, order-first order-0 order-2 order-1 no order
), play: async ({ canvasElement, step }) => { await step("Order classes are applied correctly", async () => { const orderFirst = canvasElement.querySelector(".col-order-first"); expect(orderFirst).toBeInTheDocument(); const orderLast = canvasElement.querySelector(".col-order-last"); expect(orderLast).toBeInTheDocument(); const order1 = canvasElement.querySelector(".col-order-1"); expect(order1).toBeInTheDocument(); }); }, parameters: { docs: { description: { story: "Visual order (left-to-right) differs from DOM order. Screen readers follow DOM order, not visual order.", }, }, }, }; /** * Auto-Width Columns - Demonstrates content-based column widths. * Shows how auto prop creates columns that size to their content. */ export const AutoWidth: Story = { render: () => (
Auto width (short) col-6 (50% fixed) Auto width (bit longer) Button Another Button Third Button Fixed col-3 Auto fills remaining space when needed
), play: async ({ canvasElement, step }) => { await step("Auto classes are applied correctly", async () => { const autoElements = canvasElement.querySelectorAll(".col-auto"); expect(autoElements.length).toBeGreaterThan(0); }); }, }; /** * Mixed Features - Demonstrates combining span, offset, and order. * Shows complex layouts using multiple Col features together. */ export const MixedFeatures: Story = { render: () => (
span-4 offset-2 order-2 span-4 offset-0 order-1 Visually last Centered with offset col-4 auto col-4
), }; /** * Semantic HTML - Demonstrates using different element types. * Shows Col rendering as different semantic HTML elements. */ export const SemanticHTML: Story = { render: () => (
List Item 1 List Item 2 List Item 3 Article 1 Article 2 Section Element
), play: async ({ canvasElement, step }) => { await step("Renders as