Agentic BP DScode-first design system

Table

A semantic table of rows and columns, like invoices or accounts, with optional row selection, a caption and a total.

Master

Switch size and turn on selectable for the checkbox column. Data empty shows the empty row.

A list of your recent invoices.
InvoiceStatusMethodAmount
INV001PaidCredit Card$250.00
INV002PendingPayPal$150.00
INV003UnpaidBank Transfer$350.00
INV004PaidCredit Card$450.00
INV005PaidPayPal$550.00
INV006PendingBank Transfer$200.00
INV007UnpaidCredit Card$300.00
Total$2,250.00

Usage

Use Table for lists of records. It is one component: pass columns and rows as data. Headers are kit HeaderCells; string and number values become text Cells, and anything richer is a kit Cell you put in the row (badge, avatar, link, actionMenu). Number columns take numeric, which aligns them to the end with even digits. selectable adds a checkbox column: each row gets a checkbox Cell and the header a select-all that shows a dash when only some rows are picked. The caption sits under the grid; footer holds a total in the last column. With no rows, one cell spans the columns and shows emptyLabel. Search, filters and actions belong in a Toolbar above it. Every cell keeps its value on one line at any width, so a name, a contract, a date or an amount never wraps down its cell; when the columns need more room than the page has, the table grows wider than the page and the page scrolls sideways. The table keeps no scroll box of its own, because a box that scrolls on either axis is what a sticky header holds against, and the column names have to hold against the page instead. The table answers to the width of its own box: under 640px, the kit's mobile break, the first column is frozen against the start edge while the rest of the row slides under it; with selectable, the checkbox column is frozen with it, so a row can still be ticked while it is read. The column names hold at the top of the page while the rows pass under them, so they are there to read whatever row is in view. How far down they stop is set by whatever is pinned above: a pattern holding the table says so in --table-stick-top, and on its own the table holds them at the top of the page. The frozen first column holds still both ways at once. For parent and child rows, put a Cell type tree in the first column and list only the rows whose parents are open. See contracts/table.json for the full contract.

Do's

  • Records people scan, compare and pick from: invoices, accounts, products.
  • A short list of values with a total, like line items.

Don'ts

  • Do not invent TableHeader, TableRow, TableCell or a local grid of divs. Pass columns and rows.
  • Do not draw cell content yourself. Use kit Cell types for badges, people, links and row actions.
  • Do not put search or filters in the table. Use a Toolbar above it.
  • Do not use raw hex.
  • Do not wrap it in your own scrolling box or set a width on it to make it fit a phone. It scrolls sideways and freezes its first column on its own.
  • Do not force a wide table into a narrow column by letting values break mid-word. Give it the room, let it scroll sideways in its own box, or give a long-name column a maxWidth so it ends with an ellipsis.
<Table
  columns={invoiceColumns}
  rows={invoices}
  size="md"
  line="medium"
  caption="A list of your recent invoices."
  footer={total}
/>