@biem/ui

Table

A grid of rows and columns that lets users compare records.

A table arranges records in rows and their values in columns, so users compare records by reading down a column. Its header names the columns, its body holds one row per record, and a footer and a caption can summarize and name the table. Cells keep their content on one line, and the table scrolls horizontally when its columns need more room than its container offers. A row takes a background of its own while users hover over it, while a control inside it is expanded, such as the trigger of an open menu, and when it carries data-state="selected".

TransferDestinationStatusCases
4821BaselIn transit12
4822BernScheduled8
4823ZurichReceived6

Usage

table-default.tsx
import {
	Table,
	TableBody,
	TableCell,
	TableHead,
	TableHeader,
	TableRow,
} from "@biem/ui/components/ui/table";

export function TableDefault() {
	return (
		<Table>
			<TableHeader>
				<TableRow>
					<TableHead>Transfer</TableHead>
					<TableHead>Destination</TableHead>
					<TableHead>Status</TableHead>
					<TableHead>Cases</TableHead>
				</TableRow>
			</TableHeader>
			<TableBody>
				<TableRow>
					<TableCell>4821</TableCell>
					<TableCell>Basel</TableCell>
					<TableCell>In transit</TableCell>
					<TableCell>12</TableCell>
				</TableRow>
				<TableRow>
					<TableCell>4822</TableCell>
					<TableCell>Bern</TableCell>
					<TableCell>Scheduled</TableCell>
					<TableCell>8</TableCell>
				</TableRow>
				<TableRow>
					<TableCell>4823</TableCell>
					<TableCell>Zurich</TableCell>
					<TableCell>Received</TableCell>
					<TableCell>6</TableCell>
				</TableRow>
			</TableBody>
		</Table>
	);
}

Examples

With Caption

A page with several tables, or a table that users reach with a screen reader, needs a name that tells what its records are about. TableCaption provides that name as part of the table itself, so assistive technology also uses it as the name of the table.

Transfers from the warehouse this week
TransferDestinationStatusCases
4821BaselIn transit12
4822BernScheduled8
4823ZurichReceived6

Figures in a column often matter most as a sum, for example the stock of every store together. Set apart from the records in TableFooter, the sums give users the result without making them add up the rows themselves.

TransferDestinationStatusCases
4821BaselIn transit12
4822BernScheduled8
4823ZurichReceived6
Total26

Selected Row

While users work on one record, for example in a panel with its details, they need to find its row again at a glance. Once a row carries data-state with the value "selected", it stands apart from the other rows, so users keep their place as they move between the table and the details.

TransferDestinationStatusCases
4821BaselIn transit12
4822BernScheduled8
4823ZurichReceived6

With Checkbox

Some tasks apply to several records at once, such as reordering a range of products in one step. With a Checkbox in every row, users choose those records before they act, and one more checkbox selects or clears all of them together. Each chosen row also carries data-state with the value "selected", so users see the whole selection while they scan the table.

TransferDestinationStatusCases
4821BaselIn transit12
4822BernScheduled8
4823ZurichReceived6

With Actions

Correcting a quantity or cancelling an order concerns a single record, so the action belongs with that record. Gathered in a DropdownMenu, the actions stay within reach in every row without crowding the figures, and the row remains marked while its menu is open, so users see which record they are acting on.

TransferDestinationStatusCasesActions
4821BaselIn transit12
4822BernScheduled8
4823ZurichReceived6

Horizontal Scroll

On a narrow screen or in a side panel, a table often has less room than its columns need. Instead of wrapping its values onto several lines, the table then scrolls horizontally, so each record stays on one line and users read it across all its columns.

TransferOriginDestinationStatusCasesWeightDelivery window
4821Central warehouseBaselIn transit1296 kg6:00 to 8:00
4822Central warehouseBernScheduled864 kg6:00 to 8:00
4823Regional warehouseZurichReceived648 kg7:00 to 9:00

With Frame

Where a table sits among forms, text or charts, its records can blend into the content around it. Wrapped in a TableFrame, the table forms a contained unit, so users see at once where its records begin and end.

TransferDestinationStatusCases
4821BaselIn transit12
4822BernScheduled8
4823ZurichReceived6

API Reference

Table

Table holds the caption, the header, the body and the footer, and scrolls horizontally when it is wider than its container. It renders a table inside a div and has no props of its own.

TableHeader

TableHeader groups the rows that name the columns. It renders a thead and has no props of its own.

TableBody

TableBody groups the rows that hold the records. It renders a tbody and has no props of its own.

TableFooter

TableFooter summarizes the columns below the body, for example with a total, and a border and a background of its own set it apart from the body. It renders a tfoot and has no props of its own.

TableRow

TableRow holds the heads or the cells of one row and takes a background of its own while users hover over it, while a control inside it is expanded, and when it carries data-state="selected". It renders a tr and has no props of its own.

TableHead

TableHead names a column and drops its right padding when it contains a checkbox. It renders a th and has no props of its own.

TableCell

TableCell holds one value of a row and drops its right padding when it contains a checkbox. It renders a td and has no props of its own.

TableCaption

TableCaption names the table for users and assistive technology and appears below the table. It renders a caption and has no props of its own.