Files
skills/docs/ui/react/react-ui/src/components/table/table.md
2026-05-29 08:20:56 +01:00

7.1 KiB

Table

(no submodules)

- table.variants — `tableVariants` and its eight sub-…
  • table.variants — tableVariants and its eight sub-component cva resolvers (tableHeaderVariants, tableBodyVariants, `tableFooterVari…

  • table.variants — tableVariants and its eight sub-…

  • table.variants — tableVariants and its eight sub-component cva resolvers (tableHeaderVariants, tableBodyVariants, `tableFooterVari…

  • table.variants — tableVariants and its eight sub-…

  • table.variants — tableVariants and its eight sub-component cva resolvers (tableHeaderVariants, tableBodyVariants, `tableFooterVari…

  • table.variants — tableVariants and its eight sub-…

  • table.variants — tableVariants and its eight sub-component cva resolvers (tableHeaderVariants, tableBodyVariants, `tableFooterVari…

  • table.variants — tableVariants and its eight sub-component cva resolvers (tableHeaderVariants, tableBodyVariants, `tableFooterVari…

Purpose

<Table> is the chassis pure-HTML table family — <Table> (root, wrapping <table>), <TableHeader> (<thead>), <TableBody> (<tbody>), <TableFooter> (<tfoot>), <TableRow> (<tr>), <TableHead> (<th>), <TableCell> (<td>), <TableCaption> (<caption>). The chassis exposes NO variants — typography and spacing are baked in so every chassis table renders consistently across consumers. The root wraps the native <table> in an overflow-auto container so wide tables scroll horizontally without breaking the layout.

For a headless data-table with sorting, pagination, and selection on top of these primitives, use <DataTable>.

Features

  • Eight composition primitives mapping 1:1 to native HTML table elements.
  • overflow-auto wrapper on the root so wide tables scroll horizontally.
  • Logical-property text alignment (text-start on <TableHead>) so RTL renders correctly.
  • Hover + selected (data-state="selected") row states on <TableRow>.
  • Footer reads as a summary surface (bg-muted/50 font-medium).
  • Caption sits below the table (caption-bottom) per conventional reading order.
  • All sub-components forward refs to their underlying native elements.

Usage: Basic Example

import {
    Table,
    TableBody,
    TableCaption,
    TableCell,
    TableHead,
    TableHeader,
    TableRow,
} from "@suaveplan/react-ui";

interface Invoice {
    readonly id: string;
    readonly status: string;
    readonly amount: string;
}

export function InvoiceTable({ invoices }: { invoices: Invoice[] }) {
    return (
        <Table>
            <TableCaption>A list of recent invoices.</TableCaption>
            <TableHeader>
                <TableRow>
                    <TableHead>ID</TableHead>
                    <TableHead>Status</TableHead>
                    <TableHead className="text-end">Amount</TableHead>
                </TableRow>
            </TableHeader>
            <TableBody>
                {invoices.map((invoice) => (
                    <TableRow key={invoice.id}>
                        <TableCell>{invoice.id}</TableCell>
                        <TableCell>{invoice.status}</TableCell>
                        <TableCell className="text-end">
                            {invoice.amount}
                        </TableCell>
                    </TableRow>
                ))}
            </TableBody>
        </Table>
    );
}

Usage: Advanced Example

import {
    Table,
    TableBody,
    TableCell,
    TableFooter,
    TableHead,
    TableHeader,
    TableRow,
} from "@suaveplan/react-ui";

export function OrderTotals({
    orders,
    grandTotal,
}: {
    orders: Array<{ id: string; line: string; amount: number }>;
    grandTotal: number;
}) {
    return (
        <Table>
            <TableHeader>
                <TableRow>
                    <TableHead>Order</TableHead>
                    <TableHead>Line</TableHead>
                    <TableHead className="text-end">Amount</TableHead>
                </TableRow>
            </TableHeader>
            <TableBody>
                {orders.map((order) => (
                    <TableRow key={order.id}>
                        <TableCell>{order.id}</TableCell>
                        <TableCell>{order.line}</TableCell>
                        <TableCell className="text-end">
                            ${order.amount.toFixed(2)}
                        </TableCell>
                    </TableRow>
                ))}
            </TableBody>
            <TableFooter>
                <TableRow>
                    <TableCell colSpan={2}>Total</TableCell>
                    <TableCell className="text-end">
                        ${grandTotal.toFixed(2)}
                    </TableCell>
                </TableRow>
            </TableFooter>
        </Table>
    );
}

API Reference

<Table>

forwardRef<HTMLTableElement, TableProps> — root <table> wrapped in <div className="relative w-full overflow-auto">.

<TableHeader>, <TableBody>, <TableFooter>

forwardRef<HTMLTableSectionElement, …> — <thead>, <tbody>, <tfoot> row groups.

<TableRow>

forwardRef<HTMLTableRowElement, TableRowProps> — <tr>. Hover + data-state="selected" background.

<TableHead>

forwardRef<HTMLTableCellElement, TableHeadProps> — <th> header cell.

<TableCell>

forwardRef<HTMLTableCellElement, TableCellProps> — <td> body cell.

<TableCaption>

forwardRef<HTMLTableCaptionElement, TableCaptionProps> — <caption> rendered below the table.

Errors

The Table components do NOT call useTranslation() so they do not interact with the i18n provider. Children carrying user-perceivable text must be resolved at the call site.

Implementation Notes

  • The chassis intentionally exposes NO variant axis on any sub-component — tables are pure-data surfaces and every chassis table should look the same. Consumers wanting different surfaces (zebra striping, dense layouts) override at the call site via className or register variantOverrides on their theme plugin.
  • The root wraps the native <table> in <div className="relative w-full overflow-auto"> so wide tables scroll horizontally without breaking the page layout. This means refs forwarded to <Table> reach the inner <table>, NOT the outer <div>.
  • <TableCaption> always renders below the table thanks to caption-bottom on the root. Always include a caption (visually-hidden via className="sr-only" is acceptable) so screen-readers announce the table's purpose; tables without captions are unintelligible to screen-reader users.
  • text-start on <TableHead> uses Tailwind's logical-property class so the alignment flips automatically in RTL layouts. The same applies to text-end for right-aligned numeric columns — never use text-left / text-right in chassis-rendered tables.
  • The chassis does NOT inject any data-cell-binding behaviour. For a headless data-table with sorting, pagination, and selection on top of these primitives, use <DataTable> (which renders into the same <Table> family).