# Table

> A data table built from native table elements, with a caption, row sizes, and a container that scrolls sideways on narrow screens.

- Name: `table`
- Status: beta
- Categories: data, display
- File: the install writes `table.tsx` to your `ui` alias, `@/components/ui` by default.
- Gallery: https://arbokui.com/components/table
- Registry item: https://arbokui.com/r/table.json

## Install

1. Add the registry to `components.json`. Do this first, once:

   ```bash
   npx shadcn@latest registry add "@arbokui=https://arbokui.com/r/{name}.json"
   ```

   The command writes this entry. You can also add it by hand:

   ```json
   {
     "registries": {
       "@arbokui": "https://arbokui.com/r/{name}.json"
     }
   }
   ```

   Without this step, the shadcn CLI looks up `@arbokui` in a public list that Arbokui does not control.

2. Add the theme once per app. It replaces your color tokens with ones checked for contrast:

   ```bash
   npx shadcn@latest add @arbokui/theme
   ```

3. Add the component:

   ```bash
   npx shadcn@latest add @arbokui/table
   ```

## Use it for

- Showing records people compare across columns: invoices, members, orders, results.
- Name every table with a TableCaption, as the first part inside Table.
- Put the column names in a TableHeader row of TableHead cells. Use TableHead with scope="row" for a cell that names its row.
- Pass scrollLabel when the table can be wider than its container, like on a phone. It makes the container a named region keyboard users can scroll.
- Use size to set row height: sm for dense data, md by default, lg for short tables with room to breathe.
- Right-align numbers with className="text-right" on their TableHead and TableCell, so digits line up.
- For no rows, render one row with a single TableCell whose colSpan covers every column, and say why it is empty.

## Avoid it for

- Laying out a page or a form. Use grid or flex. A table tells screen readers the content is data.
- One column of items. Use a list.
- Sorting, filtering, selecting rows, or editing cells. This table only displays. Add those with real buttons and inputs in the cells.
- Very long text in a cell. Cells do not wrap, so a paragraph makes the table very wide. Pass className="whitespace-normal" to that cell.

## Props

- `size`: `"sm" | "md" | "lg"`. Default `"md"`. On Table. Row height and cell padding: a one-line row is as tall as a control of the same size. Density scales it.
- `scrollLabel`: `string`. On Table. Makes the scroll container a focusable region with this name, so keyboard users can scroll a wide table. Use the caption's words.
- `Table`: `Omit<ComponentProps<"table">, "color"> & { size?, scrollLabel? }`. A \<table> inside a container that scrolls sideways. className and other props go on the \<table>.
- `TableCaption`: `Omit<ComponentProps<"caption">, "color">`. Part. The table's name. Put it first inside Table. It shows below the table, left-aligned.
- `TableHeader`: `Omit<ComponentProps<"thead">, "color">`. Part. The header row group. Its rows take no hover fill.
- `TableBody`: `Omit<ComponentProps<"tbody">, "color">`. Part. The body row group.
- `TableFooter`: `Omit<ComponentProps<"tfoot">, "color">`. Part. A footer row group for totals, on a muted fill.
- `TableRow`: `Omit<ComponentProps<"tr">, "color">`. Part. One row, with a bottom border and a muted fill on hover.
- `TableHead`: `Omit<ComponentProps<"th">, "color">`. Part. A header cell, in muted-foreground. Does not wrap.
- `TableCell`: `Omit<ComponentProps<"td">, "color">`. Part. A data cell. Does not wrap. Pass className="whitespace-normal" to let it wrap.
- `className`: `string`. Extra classes on any part. Later classes win, so className="py-4" on a cell replaces its padding.

## Accessibility

- Every part is the native element: \<table>, \<caption>, \<thead>, \<tbody>, \<tfoot>, \<tr>, \<th>, and \<td>. Screen readers can move by row and column and read each cell's header.
- TableCaption names the table. Screen readers read it when they reach the table.
- A \<caption> must be the first child of its \<table>, so put TableCaption first.
- scrollLabel makes the container a role="region" with that name and tabIndex=0, so keyboard users can Tab to it and scroll with the arrow keys. It shows the shared focus ring.
- Without scrollLabel, the container adds no tab stop and no name. Some browsers let keyboard users focus a container that scrolls. Do not count on it.
- Header cells use muted-foreground and body text uses the page's foreground. The theme tests hold both to 4.5:1 on the page and on cards.
- The row hover fill and the footer fill are muted at 50% over the page. Text on them sits between two pairs the theme tests hold to 4.5:1.

## Examples

### Invoices with a caption and a total

```tsx
<Table>
  <TableCaption>Recent invoices</TableCaption>
  <TableHeader>
    <TableRow>
      <TableHead>Invoice</TableHead>
      <TableHead>Status</TableHead>
      <TableHead className="text-right">Amount</TableHead>
    </TableRow>
  </TableHeader>
  <TableBody>
    <TableRow>
      <TableCell className="font-medium">INV-001</TableCell>
      <TableCell>Paid</TableCell>
      <TableCell className="text-right">$250.00</TableCell>
    </TableRow>
    <TableRow>
      <TableCell className="font-medium">INV-002</TableCell>
      <TableCell>Pending</TableCell>
      <TableCell className="text-right">$150.00</TableCell>
    </TableRow>
  </TableBody>
  <TableFooter>
    <TableRow>
      <TableCell colSpan={2}>Total</TableCell>
      <TableCell className="text-right">$400.00</TableCell>
    </TableRow>
  </TableFooter>
</Table>
```

### A wide table on a phone

```tsx
<Table scrollLabel="Team members" size="sm">
  <TableCaption>Team members</TableCaption>
  <TableHeader>
    <TableRow>
      <TableHead>Name</TableHead>
      <TableHead>Email</TableHead>
      <TableHead>Role</TableHead>
      <TableHead>Last active</TableHead>
    </TableRow>
  </TableHeader>
  <TableBody>
    <TableRow>
      <TableCell>Ada Lovelace</TableCell>
      <TableCell>ada@example.com</TableCell>
      <TableCell>Owner</TableCell>
      <TableCell>2 minutes ago</TableCell>
    </TableRow>
  </TableBody>
</Table>
```

### Row headers

```tsx
<Table>
  <TableCaption>Plan limits</TableCaption>
  <TableHeader>
    <TableRow>
      <TableHead>Plan</TableHead>
      <TableHead className="text-right">Seats</TableHead>
    </TableRow>
  </TableHeader>
  <TableBody>
    <TableRow>
      <TableHead scope="row">Free</TableHead>
      <TableCell className="text-right">3</TableCell>
    </TableRow>
    <TableRow>
      <TableHead scope="row">Pro</TableHead>
      <TableCell className="text-right">25</TableCell>
    </TableRow>
  </TableBody>
</Table>
```

### No rows yet

```tsx
<Table>
  <TableCaption>Orders</TableCaption>
  <TableHeader>
    <TableRow>
      <TableHead>Order</TableHead>
      <TableHead>Customer</TableHead>
      <TableHead className="text-right">Total</TableHead>
    </TableRow>
  </TableHeader>
  <TableBody>
    <TableRow>
      <TableCell colSpan={3} className="h-24 text-center text-muted-foreground">
        No orders yet.
      </TableCell>
    </TableRow>
  </TableBody>
</Table>
```
