Table
Calm, inset rows with a header that sticks, whole-row links and actions that appear on hover.
Invoices
10Installation
npx shadcn@latest add @quireui/tableUsage
<Table aria-label="Invoices">
<TableHeader>
<TableRow>
<TableHead>Invoice</TableHead>
<TableHead align="end">Amount</TableHead>
</TableRow>
</TableHeader>
<TableBody>
<TableRow>
<TableCell>
<TableLink href="/invoices/1042">INV-1042</TableLink>
</TableCell>
<TableCell align="end">$4,200.00</TableCell>
</TableRow>
</TableBody>
</Table>Everything sits inset from the edge. The header stands on a hairline and stays out of the way, a footer gets a soft band so totals keep their weight, a hovered row lights up as one rounded shape, and the dividers start where the text starts. The tints come from the surface colours, so they keep their warmth in dark mode. Rows follow density, 44px by default.
This is the presentational table: it styles rows you render. For sorting, filtering, selection and very long lists built in, see the Data table in Pro.
Scrolling
Give the table a height with containerClassName and it scrolls inside its box, with the library's slim scroll bars that only show while you scroll or hover. The header sticks, and a soft shadow appears under it only once rows are scrolled beneath it; the same for a TableFooter, whose shadow fades as you reach the last row. Both are driven by the scroll position in CSS, with no listeners.
When a row gets keyboard focus, the table scrolls it clear of the sticky header and footer instead of leaving it underneath them.
Cells stay on one line, which is what data wants. Pass whitespace-normal to a cell for a column of prose.
Row links
Put a TableLink in the cell that names the row, and the whole row opens it. It stays one real link, so Tab reaches it once per row, the focus ring outlines the row, and middle-click or "open in new tab" work. Pass render={<Link />} to use your router's link.
Buttons inside the row, like the actions menu, keep their own clicks.
Row actions
TableActions is the last cell, for a menu or a couple of icon buttons. They appear when you hover the row or tab into it, stay while their menu is open, and are always visible on touch screens, so a long table stays calm without hiding anything.
Numbers and sorting
align="end" on a TableHead and its cells right-aligns the column with tabular numbers, so amounts line up digit by digit.
onSort turns a header into a button, and sort shows the direction with an arrow and announces it to screen readers. On right-aligned columns the arrow sits before the label, so the label stays in line with the numbers. Sorting the rows is up to you; the example above sorts by Amount and Due.
Empty
TableEmpty is one row across every column, with room for a message and a way out.
Sticky column
sticky on the first TableHead and its cells keeps the column in view on wide tables. A shadow appears at its edge once you scroll sideways.
Selected rows
data-selected on a TableRow gives it a stronger tint, for the row whose details are open or the one being picked.
Accessibility
It is a real table, so screen readers can move by row and column and read each cell with its header. Give it an aria-label. A sortable header is read with its sort direction, and a row link is read once, named by its cell.
| Key | Action |
|---|---|
| Tab | Moves to the next row link, then to that row's actions. |
| Enter | Opens the focused row link. |
| Arrow keys | Scroll the table when it is focused and overflows. |
Table or something else?
- A list with one line per item and no columns: a plain list.
- Sorting, filtering, column visibility and row selection: the Data table in Pro.
API reference
Table
Rows of data with a sticky header and footer, inset highlights and soft scroll edges.
Prop
Type
Also takes every <table> attribute. Style it with [data-slot="table"].
--table-bg: The table's background, which its sticky parts and insets are drawn in. Set it when the table sits on something other than the surface.
TableHeader
Also takes every <thead> attribute. Style it with [data-slot="table-header"].
TableHead
Prop
Type
Also takes every <th> attribute. Style it with [data-slot="table-head"].
TableBody
Also takes every <tbody> attribute. Style it with [data-slot="table-body"].
TableFooter
Totals and summaries. Sticks to the bottom while there are rows below it.
Also takes every <tfoot> attribute. Style it with [data-slot="table-footer"].
TableRow
Also takes every <tr> attribute. Style it with [data-slot="table-row"].
TableCell
Prop
Type
Also takes every <td> attribute. Style it with [data-slot="table-cell"].
TableLink
The row's main link, e.g. the invoice number. It covers the whole row, so anywhere on the row opens it, while it stays one real link for the keyboard, middle-click and "open in new tab".
Also takes every <a> attribute.
TableActions
Buttons and menus at the end of a row. They show on hover and focus so a long table stays calm, stay while their menu is open, and are always there on touch screens.
Also takes every <td> attribute.
TableEmpty
One row across every column for when there is nothing to show, e.g. no search results.
Also takes every <td> attribute. Style it with [data-slot="table-empty"].
TableCaption
Also takes every <caption> attribute. Style it with [data-slot="table-caption"].