Table
A styled native table. All semantics come from the elements themselves (rows, header cells, caption), so screen-reader table navigation works as usual. No sorting, selection or pagination: that's a data table.
WAI-ARIA patternInstallation
npx nuecrea-ui add tableUsage
import * as Table from '@/components/ui/table';
const invoices = [
{ id: 'INV-001', status: 'Paid', method: 'Card', amount: '$250.00' },
{ id: 'INV-002', status: 'Pending', method: 'Bank transfer', amount: '$150.00' },
{ id: 'INV-003', status: 'Unpaid', method: 'Card', amount: '$350.00' },
];
export default function TableStory() {
return (
<main className="max-w-xl">
<Table.Container>
<Table.Root>
<Table.Caption>Recent invoices</Table.Caption>
<Table.Header>
<Table.Row>
<Table.Head scope="col">
Invoice
</Table.Head>
<Table.Head scope="col">
Status
</Table.Head>
<Table.Head scope="col">
Method
</Table.Head>
<Table.Head scope="col" className="text-right">
Amount
</Table.Head>
</Table.Row>
</Table.Header>
<Table.Body>
{invoices.map((inv) => (
<Table.Row key={inv.id}>
<Table.Cell className="font-medium">
{inv.id}
</Table.Cell>
<Table.Cell>{inv.status}</Table.Cell>
<Table.Cell>{inv.method}</Table.Cell>
<Table.Cell className="text-right">
{inv.amount}
</Table.Cell>
</Table.Row>
))}
</Table.Body>
<Table.Footer>
<Table.Row>
<Table.Cell colSpan={3}>
Total
</Table.Cell>
<Table.Cell className="text-right">
$750.00
</Table.Cell>
</Table.Row>
</Table.Footer>
</Table.Root>
</Table.Container>
</main>
);
}API reference
Table.Container
Optional scroll wrapper: lets a wide table scroll sideways instead of overflowing the page. Renders <div>.
Table.Root
The table. Renders <table>.
Table.Header
Header row group. Renders <thead>.
Table.Body
Body row group. Renders <tbody>.
Table.Row
A row. Highlights on hover. Renders <tr>.
Table.Head
A header cell. Add scope="col" or scope="row" as usual. Renders <th>.
Table.Cell
A data cell. Renders <td>.
Table.Caption
The table's accessible name, shown under it. Renders <caption>.