Table

The product's table: a sticky caps header on --surface-2, three densities, numeric cells in right-aligned tabular mono, a count line under it, and an empty state that keeps the header. The first column reads in --text-1, the rest in --text-2. An interactive row with onClick is a tab stop and opens on Enter or Space; keys pressed on a control inside it are left to that control, and a row that holds its own link passes tabIndex={-1} so the link is the one stop. One dense table per viewport, never two in adjacent bands, and never the first thing on a screen.

import { Table, THead, TBody, Tr, Th, Td, TGroup } from "@puckoops/camelot";
ItemClientDirectionDueAmount
Invoice 2041 — brand systemNordvik AtelierOverdue02 Oct£14,200
Studio insurance renewalInternalPayable04 Oct£1,880
Invoice 2044 — packaging artBrightwater FoodsReceivable09 Oct£9,600
Invoice 2046 — September retainerPurslane StudioReceivable15 Oct£3,150
Print run, signage pilotNordvik AtelierPayable21 Oct£2,260
NameDescriptionDefaultControl
density
52, 44 or 36px rows
"relaxed""default""compact"
"default"
density
footer
A caption line under the table: the count, totals.
ReactNode
--
empty
Shown in the body when there are no rows, keeping the header visible.
ReactNode
--
isEmpty
Shows empty in place of the rows
boolean
-
minWidth
Below this the table scrolls sideways
number
640
frameClassName
string
-

Also takes HTMLAttributes<HTMLTableElement>.

When to use

Use Table for rows people scan. Density follows the job: relaxed for tables people read, default for the product, compact for a second table or a drawer. One dense table per viewport; never two tables in adjacent bands. A Tr with interactive and onClick is a tab stop that opens on Enter or Space, leaving keys on controls inside it alone; a row that contains its own link should pass tabIndex={-1} so the link is the one stop.

  • Use Cards/ListCard instead for five rows or fewer of label · value.
  • Use Board instead when rows are work items moving between states.

Examples

Relaxed

52px rows, for a table people read rather than scan.

ItemClientDirectionDueAmount
Invoice 2041 — brand systemNordvik AtelierOverdue02 Oct£14,200
Studio insurance renewalInternalPayable04 Oct£1,880
Invoice 2044 — packaging artBrightwater FoodsReceivable09 Oct£9,600
Invoice 2046 — September retainerPurslane StudioReceivable15 Oct£3,150
Print run, signage pilotNordvik AtelierPayable21 Oct£2,260

Compact

36px rows, for a second table or a drawer.

ItemClientDirectionDueAmount
Invoice 2041 — brand systemNordvik AtelierOverdue02 Oct£14,200
Studio insurance renewalInternalPayable04 Oct£1,880
Invoice 2044 — packaging artBrightwater FoodsReceivable09 Oct£9,600
Invoice 2046 — September retainerPurslane StudioReceivable15 Oct£3,150
Print run, signage pilotNordvik AtelierPayable21 Oct£2,260

Empty

Filtered to nothing: the header stays so the reader keeps their place.

ItemClientDirectionDueAmount

Nothing matches these filters.

Grouped

TGroup rows in caps on --surface-2 split the list by due date.

TaskStatusPriorityDue
Overdue
Brand system rolloutBlockedHigh28 Sep
This week
Packaging die-line auditIn ProgressMedium02 Oct
Signage proofs to printIn ReviewMedium03 Oct
Later
Rebrand discovery notesBacklogLow12 Oct
Annual report photographyTo DoLow20 Oct

Numeric

Numbers right-aligned in tabular mono, so the columns line up digit for digit.

ClientInvoicedPaidOutstandingDays late
Nordvik Atelier£48,200£34,000£14,20012
Brightwater Foods£21,600£12,000£9,6000
Purslane Studio£9,450£6,300£3,1500
Halden & Moss£2,480£0£2,48031

Selected Row

Click a row, or Tab to it and press Enter: the selected row takes --surface-3 and an ink edge.

ItemClientDirectionDueAmount
Invoice 2041 — brand systemNordvik AtelierOverdue02 Oct£14,200
Studio insurance renewalInternalPayable04 Oct£1,880
Invoice 2044 — packaging artBrightwater FoodsReceivable09 Oct£9,600
Invoice 2046 — September retainerPurslane StudioReceivable15 Oct£3,150
Print run, signage pilotNordvik AtelierPayable21 Oct£2,260

Row With Its Own Link

Rows that contain their own link pass tabIndex={-1}: the pointer can still click the row, and the keyboard stops once per row, on the link.

ItemClientDirectionDueAmount
Invoice 2041 — brand systemNordvik AtelierOverdue02 Oct£14,200
Studio insurance renewalInternalPayable04 Oct£1,880
Invoice 2044 — packaging artBrightwater FoodsReceivable09 Oct£9,600
Invoice 2046 — September retainerPurslane StudioReceivable15 Oct£3,150
Print run, signage pilotNordvik AtelierPayable21 Oct£2,260

All Variants

The three densities, one above the other for comparison only; a screen never stacks tables like this.

relaxed
ItemClientDirectionDueAmount
Invoice 2041 — brand systemNordvik AtelierOverdue02 Oct£14,200
Studio insurance renewalInternalPayable04 Oct£1,880
Invoice 2044 — packaging artBrightwater FoodsReceivable09 Oct£9,600
Invoice 2046 — September retainerPurslane StudioReceivable15 Oct£3,150
Print run, signage pilotNordvik AtelierPayable21 Oct£2,260
default
ItemClientDirectionDueAmount
Invoice 2041 — brand systemNordvik AtelierOverdue02 Oct£14,200
Studio insurance renewalInternalPayable04 Oct£1,880
Invoice 2044 — packaging artBrightwater FoodsReceivable09 Oct£9,600
Invoice 2046 — September retainerPurslane StudioReceivable15 Oct£3,150
Print run, signage pilotNordvik AtelierPayable21 Oct£2,260
compact
ItemClientDirectionDueAmount
Invoice 2041 — brand systemNordvik AtelierOverdue02 Oct£14,200
Studio insurance renewalInternalPayable04 Oct£1,880
Invoice 2044 — packaging artBrightwater FoodsReceivable09 Oct£9,600
Invoice 2046 — September retainerPurslane StudioReceivable15 Oct£3,150
Print run, signage pilotNordvik AtelierPayable21 Oct£2,260