Table
Four thin wrappers over the real table elements — bonus history, withdrawal lists. They add the house borders and padding and nothing else, so the semantics stay native.
import { Table, TableRow, TableHeaderCell, TableCell } from '@/components/ui/Table';Source: src/components/ui/Table.tsx
Examples
A data table
Note the plain <thead>/<tbody>: those are not wrapped, because there is nothing to style on them and a wrapper that does nothing is a wrapper someone has to learn.
| Store | Date | Cashback |
|---|---|---|
| Example Store | 12.8.2026 | 4,50 € |
| Another Store | 3.8.2026 | 12,00 € |
Props
<Table> props
No props of its own.
Also accepts everything in HTMLAttributes<HTMLTableElement> — so native attributes (id, onClick, aria-*, data-*) pass straight through.
<TableRow> props
No props of its own.
Also accepts everything in HTMLAttributes<HTMLTableRowElement> — so native attributes (id, onClick, aria-*, data-*) pass straight through.
<TableHeaderCell> props
No props of its own.
Also accepts everything in ThHTMLAttributes<HTMLTableCellElement> — so native attributes (id, onClick, aria-*, data-*) pass straight through.
<TableCell> props
No props of its own.
Also accepts everything in TdHTMLAttributes<HTMLTableCellElement> — so native attributes (id, onClick, aria-*, data-*) pass straight through.
Accessibility
- Real <table>/<th>/<td>, so a screen reader announces each cell with its column.
- Scrolling wrapper: give it a tabindex if the table is wide, or a keyboard user cannot reach the columns off screen.
Usage
Do
- Wrap it in `overflow-x-auto`. A table is the one thing that legitimately doesn’t fit a phone, and the page must not scroll sideways.
- Use TableHeaderCell for headers — it renders a real <th>, which is what makes the table navigable.
Don’t
- Don’t use a table for layout. ESLint forbids a raw <table> for that reason.
- Don’t stack Rows to fake a table; column alignment stops working the moment content varies.