import type { Meta, StoryObj } from '@storybook/react' import { type ColumnDef, flexRender, getCoreRowModel, useReactTable, getPaginationRowModel, } from '@tanstack/react-table' import { useState } from 'react' import { SvgLineArrowDown1, SvgLineArrowUp1 } from '@chainlink/blocks-icons' import { Button, ButtonIcon } from '../Button' import { Tag } from '../Tag' import { Typography } from '../Typography' import { TableRoot, TableHeader, TableBody, TableHead, TableRow, TableCell, } from './Table' import { TablePagination } from './TablePagination' const meta: Meta = { title: 'Blocks/Table/Primitives', component: TableRoot, parameters: { layout: 'padded', }, argTypes: { className: { control: 'text', description: 'Additional CSS classes for custom styling', }, children: { control: false, description: 'Table content and sub-components', }, }, } export default meta type Story = StoryObj const sampleData = [ { name: 'John Doe', email: 'john.doe@example.com', role: 'Admin', status: 'Active', }, { name: 'Jane Smith', email: 'jane.smith@example.com', role: 'User', status: 'Active', }, { name: 'Bob Johnson', email: 'bob.johnson@example.com', role: 'User', status: 'Inactive', }, ] export const Default: Story = { render: (_args) => ( Name Email Role Status {sampleData.map((row, index) => ( {row.name} {row.email} {row.role} {row.status} ))} ), } export const WithActions: Story = { render: (_args) => ( Name Email Role Actions {sampleData.map((row, index) => ( {row.name} {row.email} {row.role}
))}
), } const invoiceData = [ { invoice: 'INV-001', status: 'Paid', method: 'Credit Card', amount: '$250.00', }, { invoice: 'INV-002', status: 'Pending', method: 'PayPal', amount: '$150.00', }, { invoice: 'INV-003', status: 'Unpaid', method: 'Bank Transfer', amount: '$350.00', }, { invoice: 'INV-004', status: 'Paid', method: 'Credit Card', amount: '$450.00', }, ] export const InvoiceTable: Story = { render: (_args) => ( Invoice Status Method Amount {invoiceData.map((row, index) => ( {row.invoice} {row.status} {row.method} {row.amount} ))} ), } const productData = [ { product: 'Wireless Mouse', category: 'Electronics', stock: 45, price: '$29.99', }, { product: 'Mechanical Keyboard', category: 'Electronics', stock: 12, price: '$129.99', }, { product: 'USB-C Cable', category: 'Accessories', stock: 0, price: '$19.99', }, { product: 'Monitor Stand', category: 'Furniture', stock: 8, price: '$79.99', }, ] export const ProductTable: Story = { render: (_args) => ( Product Category Stock Price {productData.map((row, index) => ( {row.product} {row.category} {row.stock} {row.price} ))} ), } export const EmptyTable: Story = { render: (_args) => ( Name Email Role Status No data available ), } export const SingleColumn: Story = { render: (_args) => ( Task Complete project documentation Review pull requests Update dependencies ), } const expandableData = [ { event: 'Event 1', status: 'Success', method: 'GET', timestamp: '2024-01-15 10:30', details: 'This event completed successfully with no errors.', }, { event: 'Event 2', status: 'Failure', method: 'POST', timestamp: '2024-01-15 11:15', details: 'Error: Connection timeout after 30 seconds. Please check network connectivity and try again.', hasError: true, }, { event: 'Event 3', status: 'Success', method: 'PUT', timestamp: '2024-01-15 12:00', details: 'Resource updated successfully.', }, ] const ExpandableTableRow = ({ data, }: { data: (typeof expandableData)[number] }) => { const [isExpanded, setIsExpanded] = useState(false) const hasDetails = data.hasError || data.details return ( <> {data.event} {data.status} {data.method} {data.timestamp} {hasDetails && ( setIsExpanded(!isExpanded)} variant="ghost" size="sm" > {isExpanded ? : } )} {isExpanded && hasDetails && (
{data.details}
)} ) } export const ExpandableRows: Story = { render: (_args) => ( Event Status Method Timestamp {expandableData.map((row, index) => ( ))} ), } type PaginatedDataType = { id: string name: string email: string role: string } const paginatedData: PaginatedDataType[] = Array.from( { length: 45 }, (_, i) => ({ id: `user-${i + 1}`, name: `User ${i + 1}`, email: `user${i + 1}@example.com`, role: ['Admin', 'User', 'Moderator', 'Guest'][i % 4], }), ) const paginatedColumns: ColumnDef[] = [ { accessorKey: 'name', header: 'Name', cell: ({ getValue }) => ( {getValue() as string} ), }, { accessorKey: 'email', header: 'Email', cell: ({ getValue }) => ( {getValue() as string} ), }, { accessorKey: 'role', header: 'Role', cell: ({ getValue }) => ( {getValue() as string} ), }, ] export const WithPagination: Story = { render: (_args) => { const PaginatedTableExample = () => { const table = useReactTable({ data: paginatedData, columns: paginatedColumns, getCoreRowModel: getCoreRowModel(), getPaginationRowModel: getPaginationRowModel(), initialState: { pagination: { pageSize: 10, }, }, }) return ( <> {table.getHeaderGroups().map((headerGroup) => ( {headerGroup.headers.map((header) => ( {header.isPlaceholder ? null : flexRender( header.column.columnDef.header, header.getContext(), )} ))} ))} {table.getRowModel().rows.map((row) => ( {row.getVisibleCells().map((cell) => ( {flexRender( cell.column.columnDef.cell, cell.getContext(), )} ))} ))} ) } return }, parameters: { docs: { source: { // This is what Storybook will show in the "Source" panel code: `const PaginatedTableExample = () => { const table = useReactTable({ data: paginatedData, columns: paginatedColumns, getCoreRowModel: getCoreRowModel(), getPaginationRowModel: getPaginationRowModel(), initialState: { pagination: { pageSize: 10 }, }, }) return ( <> {table.getHeaderGroups().map((headerGroup) => ( {headerGroup.headers.map((header) => ( {header.isPlaceholder ? null : flexRender( header.column.columnDef.header, header.getContext(), )} ))} ))} {table.getRowModel().rows.map((row) => ( {row.getVisibleCells().map((cell) => ( {flexRender(cell.column.columnDef.cell, cell.getContext())} ))} ))} ) }`, }, }, }, } export const WithDisplayPagination: Story = { render: (_args) => { const PaginatedTableDisplayExample = () => { const table = useReactTable({ data: paginatedData, columns: paginatedColumns, getCoreRowModel: getCoreRowModel(), getPaginationRowModel: getPaginationRowModel(), initialState: { pagination: { pageSize: 10, }, }, }) return ( <> {table.getHeaderGroups().map((headerGroup) => ( {headerGroup.headers.map((header) => ( {header.isPlaceholder ? null : flexRender( header.column.columnDef.header, header.getContext(), )} ))} ))} {table.getRowModel().rows.map((row) => ( {row.getVisibleCells().map((cell) => ( {flexRender( cell.column.columnDef.cell, cell.getContext(), )} ))} ))} ) } return }, parameters: { docs: { source: { code: `const PaginatedTableDisplayExample = () => { const table = useReactTable({ data: paginatedData, columns: paginatedColumns, getCoreRowModel: getCoreRowModel(), getPaginationRowModel: getPaginationRowModel(), initialState: { pagination: { pageSize: 10 }, }, }) return ( <> {table.getHeaderGroups().map((headerGroup) => ( {headerGroup.headers.map((header) => ( {header.isPlaceholder ? null : flexRender( header.column.columnDef.header, header.getContext(), )} ))} ))} {table.getRowModel().rows.map((row) => ( {row.getVisibleCells().map((cell) => ( {flexRender(cell.column.columnDef.cell, cell.getContext())} ))} ))} ) }`, }, }, }, }