import * as React from 'react'; import type { Meta, StoryObj } from '@storybook/react-vite'; import { DataTable, type DataTableColumn } from './data-table'; import { Badge } from '../badge/badge'; import { Input } from '../input/input'; type User = { id: number; name: string; email: string; role: string; status: 'active' | 'invited' | 'suspended'; seats: number; }; const users: User[] = [ { id: 1, name: 'Ada Lovelace', email: 'ada@example.com', role: 'Owner', status: 'active', seats: 12 }, { id: 2, name: 'Grace Hopper', email: 'grace@example.com', role: 'Admin', status: 'active', seats: 8 }, { id: 3, name: 'Alan Turing', email: 'alan@example.com', role: 'Member', status: 'invited', seats: 1 }, { id: 4, name: 'Katherine Johnson', email: 'katherine@example.com', role: 'Member', status: 'active', seats: 3 }, { id: 5, name: 'Barbara Liskov', email: 'barbara@example.com', role: 'Member', status: 'suspended', seats: 0 }, ]; const statusVariant = { active: 'success', invited: 'secondary', suspended: 'destructive', } as const; const columns: DataTableColumn[] = [ { key: 'name', title: 'Name', dataIndex: 'name', sortable: true }, { key: 'email', title: 'Email', dataIndex: 'email', className: 'text-muted-foreground' }, { key: 'role', title: 'Role', dataIndex: 'role', sortable: true }, { key: 'status', title: 'Status', dataIndex: 'status', render: (value) => ( {String(value)} ), }, { key: 'seats', title: 'Seats', dataIndex: 'seats', align: 'right', sortable: true }, ]; const meta = { title: 'Components/DataTable', parameters: { layout: 'padded', docs: { description: { component: 'Table for structured data. A semantic `` with the parts that make a data grid usable at scale — a sticky header, columns pinned while the rest scrolls sideways, and expandable rows. Sorting works either way round: omit `sort`/`onSortChange` and the table reorders its own rows; pass both and the header just reports intent, which is what you want when a server sorts.', }, }, }, tags: ['autodocs'], } satisfies Meta; export default meta; type Story = StoryObj; export const Default: Story = { render: () => , }; /** Click a header to sort: ascending → descending → back to the original order. */ export const Sortable: Story = { render: () => , }; export const Empty: Story = { render: () => ( ), }; /** `scroll.y` turns the header sticky; `scroll.x` plus `fixed` pins a column. */ export const StickyHeaderAndPinnedColumn: Story = { render: () => ( ({ ...u, id: u.id + 10 }))]} scroll={{ x: 900, y: 240 }} columns={[ { ...columns[0], fixed: 'left', width: 200 }, { key: 'email', title: 'Email', dataIndex: 'email', width: 240 }, { key: 'role', title: 'Role', dataIndex: 'role', width: 140 }, { key: 'status', title: 'Status', dataIndex: 'status', width: 140 }, { key: 'seats', title: 'Seats', dataIndex: 'seats', width: 100, align: 'right' }, { ...columns[3], key: 'status2', title: 'Status (pinned)', fixed: 'right', width: 160 }, ]} /> ), }; export const ExpandableRows: Story = { render: () => ( (
{record.name} joined as {record.role.toLowerCase()} and holds {record.seats} seat {record.seats === 1 ? '' : 's'}.
), rowExpandable: (record) => record.status !== 'suspended', }} /> ), }; /** * Controlled sorting. The table stops reordering rows and reports the intent * instead — swap the local `useMemo` for a query and this is server-side. */ export const ControlledSort: Story = { render: function ControlledSortStory() { const [sort, setSort] = React.useState<{ key: React.Key; direction: 'asc' | 'desc' } | null>({ key: 'seats', direction: 'desc', }); const [query, setQuery] = React.useState(''); const rows = React.useMemo(() => { const filtered = users.filter((u) => `${u.name} ${u.email}`.toLowerCase().includes(query.toLowerCase()) ); if (!sort) return filtered; const key = sort.key as keyof User; const sorted = [...filtered].sort((a, b) => String(a[key]).localeCompare(String(b[key]), undefined, { numeric: true }) ); return sort.direction === 'desc' ? sorted.reverse() : sorted; }, [query, sort]); return (
setQuery(event.target.value)} placeholder="Filter members…" className="max-w-xs" />

Sort: {sort ? `${String(sort.key)} ${sort.direction}` : 'none'}

); }, };