Table
Table — one anatomy in two sizes: a card on surface/card at radius/16 with elevation/card, an accent-dark header bar, row-header pills, 2 px dividers and no vertical lines; the Accent mode drives it (a neutral-800 bar and neutral-200 pills in multicolor — the grey SWOT).
Beta · Content blocks · packages/css/src/components/table.css · React on Base UI: @pepperui/table
.pui-table (--slide) · __table __row __cell (--header --row-header --right) · __pill __sort · row aria-selected. The last row has no divider.
Sizes across, states down.
What it is for
Section titled “What it is for”- Size slide (four columns, the first a pill column) / product (body 13 Regular, header 14 Medium, padding 12 × 16; six columns, no pills; what Data table composes)
- Header row and Rows 1–5 are exposed — edit every cell; Has row 4 / Has row 5 drop to three rows; columns 5 and 6 are switched per row (Has cell 5 / 6 on each — Figma cannot link one switch to nested rows), so keep them consistent
- Padding space/8 (the bar’s radius 8 then sits concentric in the outer 16)
- Rows sit FLUSH — no gap between them, and none under the header bar: a hover or selection wash runs from the divider above to the row’s own. The space a row needs is inside the row — the slide cell’s padding is space/16, so the 59 pitch is kept, the product row is 46, and a row-header pill is inset space/4 so stacked pills stay 8 apart
- Columns fill the width — no void at the right end of a row; give a fixed column an explicit width that fits its longest value
- Numbers right, words left; the entity column is named what the product calls it — MAFO’s header says Publisher
- On a product dashboard the bar is the NEUTRAL one — the multicolor mode’s neutral-800 bar on neutral-200 pills, the black one of the four; the deck keeps its accent bars
- A divider is a STRAIGHT line from end to end — its own rectangle under the cell, never a stroke that follows the cell’s rounded ends (the CSS part draws it as ::after over a transparent border for the same reason)
- 1200 wide for the specimen (1792 on a slide — the content width); FILL in a Card slot or the page
Use when rows of records with the same fields — publishers, campaigns, offers, users; a SWOT or a quarter plan on a slide.
Do not use when fewer than three rows or two columns (a Bullet list or a KPI row); the rows need sorting, filtering, paging or selection (Data table); the values want a chart (Chart recipes); a comparison of two things (a Card pair).
Relates to Table row, Table cell, Data table, Badge, Card, Chart recipes.
Anti-patterns zebra stripes · a coloured cell for status · numbers left-aligned · a header that is not the first row · vertical grid lines · a white table with a grey header · more than seven columns without a Data table.
Keywords: table, grid, rows, columns, data, list of records, SWOT, comp-table
Figma — page Table: Table (2 variants) · Table row (8 variants) · Table cell (12 variants)
shadcn: table
The markup — copy this
Section titled “The markup — copy this”The class, the parts, and nothing that is not in the package. The same block opens table.css.
<div class="pui-table"><table class="pui-table__table"> <thead><tr class="pui-table__row"><th class="pui-table__cell pui-table__cell--header">Publisher<span class="pui-icon pui-table__sort">…</span></th> <th class="pui-table__cell pui-table__cell--header pui-table__cell--right">Revenue</th></tr></thead> <tbody><tr class="pui-table__row"><td class="pui-table__cell pui-table__cell--row-header"><span class="pui-table__pill">Q1</span></td> <td class="pui-table__cell pui-table__cell--right">$ 8 969 916</td></tr> <tr class="pui-table__row" aria-selected="true"> … </tr></tbody></table></div><div class="pui-data-table"><div class="pui-data-table__toolbar">…</div><div class="pui-table">…</div> <div class="pui-data-table__footer"><span class="pui-data-table__range">1–5 of 118 publishers</span><nav class="pui-pagination">…</nav></div></div>The modifiers
Section titled “The modifiers”| What it is | Note | |
|---|---|---|
| Size | (none) product · --slide (on .pui-table) | — |
| Cell | __cell (body) · __cell--header · __cell--row-header (holds a __pill) · __cell--right | — |
| Row | :hover · selected = [aria-selected=“true”] or --selected | — |
| Accent | data-accent on the table or a parent drives the bar and the pills — table/header/bg and table/header/pill-tint re-resolve per mode (blue navy · red · yellow · multicolor = a neutral-800 bar on neutral-200 pills, the black one); a product dashboard’s table is the neutral one (data-accent=“multicolor” on .pui-table) | — |
Accessibility — measured, not assumed
Section titled “Accessibility — measured, not assumed”Every number here is measured on the rendered component: contrast (npm run contrast:render), the focus ring (npm run focus) and the keyboard (npm run keyboard). The floors are principle 12’s.
Contrast
Section titled “Contrast”| ink on ground | reads | floor | the matrix calls it | |
|---|---|---|---|---|
#544d4d on #dad9d9 |
5.85 | 4.5 | text.muted on ground.card.sunken (promised) | ok |
#0b0202 on #dad9d9 |
14.56 | 4.5 | text.default on ground.card.sunken (promised) | ok |
#ffffff on #231b1b |
16.88 | 4.5 | text.on-accent on surface.inverse (not-offered) | ok |
#0b0202 on #e9e9fb |
17.1 | 4.5 | KPI value, blue tile (promised) | ok |
#0b0202 on #f2f2f7 |
18.38 | 4.5 | text.default on surface.card (promised) | ok |
#ffffff on #0c0b41 |
18.42 | 4.5 | Table header label (promised) | ok |
6 distinct pair(s) rendered, 0 that axe calls a violation.
The focus ring
Section titled “The focus ring”Nothing in this component takes focus.
Keyboard
Section titled “Keyboard”Nothing in this component claims an ARIA role with a keyboard contract; its controls are ordinary ones and the browser already gives them their keys.
Tab order across the whole library is document order over 344 stops, and Shift+Tab is its exact reverse — no keyboard trap anywhere (WCAG 2.1.2).
Pepper UI v1.5.0
The Mobupps design system. 386 tokens, 88 components, 65 pages in the workshop — every page of this site generated from the repository, so nothing here is typed twice.