# Table

Shows data compared across rows and columns.

```tsx
import { Table, TableBody, TableCaption, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table"

<Table label="Orders">
  <TableCaption>Orders, October 2026</TableCaption>
  <TableHeader>
    <TableRow>
      <TableHead>Order</TableHead>
      <TableHead>Customer</TableHead>
      <TableHead className="text-right">Amount</TableHead>
    </TableRow>
  </TableHeader>
  <TableBody>
    {orders.map((order) => (
      <TableRow key={order.id}>
        <TableCell>{order.id}</TableCell>
        <TableCell>{order.customer}</TableCell>
        <TableCell className="text-right font-mono tabular-nums">{order.amount}</TableCell>
      </TableRow>
    ))}
  </TableBody>
</Table>
```

## Usage

### What you provide
- `TableHeader` with short `TableHead` labels; `TableBody` with rows; optional `TableCaption`.
- Numbers and amounts: right-aligned, `font-mono tabular-nums`, en-US format (`$1,280.00`, `Oct 21, 2026`).
- Status as a `Badge`.
- Empty state: one row with `colSpan` and a sentence saying what will appear and how to add the first item.

## Accessibility

- Use tables for data compared by rows and columns, never for layout.
- Always give it a `TableCaption` (or a heading) that explains what the data is. Column headers are `<th scope="col">`; for row headers use `<th scope="row">`.
- Static cells take no focus. When the table scrolls sideways, PUI makes the container focusable so arrows can scroll it; pass `label` to name that region.
- Sortable columns use a button in the header with the current direction exposed (`aria-sort` on the `th`); focus stays on the control after sorting.
- Row selection shows single, partial and all states; say how many records a bulk action affects before running it.
- Design loading, empty, no-match and failed states as different messages.

_Adapted from Magoo 1.6.0 by Marcelo Sales: [Tables](https://magoo.cc/en/components/structure/tables.html) (`tabelas`). Magoo is educational guidance; test the behavior in your implementation._

## API

Install:

```bash
npx @aline-aroucha/pui add table badge
```

```tsx
<Table>
  <TableCaption />
  <TableHeader>
    <TableRow>
      <TableHead />
    </TableRow>
  </TableHeader>
  <TableBody>
    <TableRow>
      <TableCell />
    </TableRow>
  </TableBody>
  <TableFooter />
</Table>
```

### Table

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `label` | `string` | — | Names the scrolling region for screen readers when the table scrolls sideways. |

### TableCaption

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `children` | `ReactNode` | — | What the data is. Always include one. |

### TableHead

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `scope` | `"col" \| "row"` | `"col"` | Which cells this header describes. |

### TableRow

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `data-state` | `"selected"` | — | Highlights a selected row. |

## Related pages

- [Badge](https://aline-aroucha.github.io/pui/components/badge.html)
- [Card](https://aline-aroucha.github.io/pui/components/card.html)
- [Skeleton](https://aline-aroucha.github.io/pui/components/skeleton.html)

---
PUI documentation · https://aline-aroucha.github.io/pui/components/table.html
