Table
Semantic data table with header styles, hover rows and a scroll wrapper so wide tables stay usable at 320px.
Preview
Live preview
| Fruit | Origin | In stock |
|---|---|---|
| Apple | Valencia | 128 |
| Pear | Lisbon | 54 |
| Cherry | Kalamata | 17 |
Usage
Examples
With a footer total
| Item | Amount |
|---|---|
| Hosting | $20.00 |
| Total | $20.00 |
<Table>
<TableHeader>
<TableRow>
<TableHead>Item</TableHead>
<TableHead className="text-right">Amount</TableHead>
</TableRow>
</TableHeader>
<TableBody>
<TableRow>
<TableCell>Hosting</TableCell>
<TableCell className="text-right">$20.00</TableCell>
</TableRow>
</TableBody>
<TableFooter>
<TableRow>
<TableCell>Total</TableCell>
<TableCell className="text-right">$20.00</TableCell>
</TableRow>
</TableFooter>
</Table>Badges as cell content
| workspace-42 | Active |
<TableCell>
<Badge variant="secondary">Active</Badge>
</TableCell>Reference
Props
| Prop | Type | Default | Description |
|---|---|---|---|
| Table | HTMLAttributes<HTMLTableElement> | — | Wraps the table in a horizontal scroll container (320px safe). |
| TableHeader / TableBody / TableFooter | HTMLAttributes<HTMLTableSectionElement> | — | Semantic sections; the footer row is not affected by the hover style. |
| TableRow | HTMLAttributes<HTMLTableRowElement> | — | Row with bottom border, hover wash and data-[state=selected] styling. |
| TableHead | ThHTMLAttributes<HTMLTableCellElement> | — | Column header; scope="col" is set for you and can be overridden. |
| TableCell | TdHTMLAttributes<HTMLTableCellElement> | — | Body cell. Add className="text-right" for numbers. |
| TableCaption | HTMLAttributes<HTMLTableCaptionElement> | — | Table description rendered below the rows. |
Accessibility
Accessibility notes
- Renders a real <table> with <th scope="col"> — screen readers announce column headers with each cell.
- Every visual row is a real <tr>; no div-based grids, so row/header relationships survive.
- Add a TableCaption: it becomes the table's accessible description.
- The wrapper scrolls horizontally instead of shrinking text — zooming to 200% still works.
- Mark the selected row with data-state="selected" plus an aria-label if selection is not otherwise explained.