Table

Structured table primitive for dense product-facing data and repeatable row rhythm.

LLM handoff

Copy a concise page brief or the full MDX source without digging through the docs shell.

ItemOwnerStatus
Launch issue 04EditorialReady
Spec revisionProductReview
Shelf imageryStudioQueued

The table primitives keep row rhythm, numeric alignment, and selection states consistent across denser data surfaces. They are intentionally simple wrappers around HTML table elements, with the Swiss styling work concentrated in spacing, borders, uppercase headers, row-state treatment, and a theme-derived surface scale that keeps dense views differentiated without leaving the active palette.

This pass expands the primitive so common product-table needs stay within the shipped API: denser layouts, lighter or stronger table chrome, row striping, sticky headers, and pinned or striped columns.

Installation

Install
Purchase access, then open /account/install to issue a registry token.

Usage

import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from "@/components/ui/table"
<Table>
  <TableHeader>
    <TableRow>
      <TableHead>Item</TableHead>
      <TableHead>Status</TableHead>
    </TableRow>
  </TableHeader>
  <TableBody>
    <TableRow>
      <TableCell>Launch issue 04</TableCell>
      <TableCell>Ready</TableCell>
    </TableRow>
  </TableBody>
</Table>
<Table surface="soft" chrome="strong" density="dense">
  <TableHeader sticky>
    <TableRow>
      <TableHead sticky="left">Record</TableHead>
      <TableHead striped>Region</TableHead>
      <TableHead numeric>Delta</TableHead>
    </TableRow>
  </TableHeader>
  <TableBody striped>
    <TableRow>
      <TableCell sticky="left">BA-1024</TableCell>
      <TableCell striped>North America</TableCell>
      <TableCell numeric>+4</TableCell>
    </TableRow>
  </TableBody>
</Table>

Why This Primitive Exists

Product tables need more than plain HTML defaults, but they do not need a full data-grid abstraction every time.

  • Use these primitives when the information is genuinely tabular and column comparison matters.
  • Keep the schema stable so users can scan down the same columns repeatedly.
  • Avoid tables for short lists that are easier to read as stacked cards or items.

Examples

Basic Structure

Start with the six core building blocks and let the content determine the column widths.

ItemOwnerStatus
Launch issue 04EditorialReady
Spec revisionProductReview
Shelf imageryStudioQueued

Numeric Columns

The Swiss table supports both the legacy data-numeric convention and a direct numeric prop on TableHead and TableCell so counts, prices, and totals line up cleanly.

RegionOrdersRevenue
North America148$42,300
Europe96$31,180
Asia Pacific74$19,640
<TableHead numeric>Revenue</TableHead>
<TableCell numeric>$42,300</TableCell>

In Context

Tables become more useful when selection, hover state, and surrounding panel hierarchy all reinforce the current row. The surrounding surface can stay on theme without collapsing back to the same neutral panel every time.

Operations table

Tables work best when the columns are stable and easy to scan row by row.
Active allocation3 rows
SKUStockStatus
CH-10418Allocated
CH-10842Available
CH-1127Backorder
<TableRow data-state="selected">
  <TableCell>CH-104</TableCell>
  <TableCell data-numeric="true">18</TableCell>
  <TableCell>Allocated</TableCell>
</TableRow>

Variants

Surface, chrome, density, and row striping are now first-class controls so tables can shift between quieter and stronger product shells without rewriting the internals.

Variant coverage

Surface, density, and row-striping can now shift without rewriting the primitive.

QueueOwnerOpenReady
North archiveResearch148
Spec intakeProduct95
Asset requestsStudio2213
Launch reviewOperations64

Sticky Zones

Sticky headers belong at the header layer, while pinned columns belong at the cell layer. That split keeps the API aligned with how real tables are composed.

Sticky and striped control

Sticky headers and pinned columns stay readable inside a narrower viewport, while striped columns remain opt-in.

RecordOwnerRegionStateDelta
BA-1024OperationsNorth AmericaQueued+4
BA-1042ResearchEuropeIn review+1
BA-1077StudioAsia PacificAllocated+7
BA-1091ProductSouth AmericaReady+2
<TableHeader sticky />
<TableBody striped />
<TableHead sticky="left">Record</TableHead>
<TableCell sticky="left">BA-1024</TableCell>
<TableHead striped>Region</TableHead>
<TableCell striped>North America</TableCell>

Guidance

Use Tables For Comparison

  • Reach for a table when users need to scan several records against the same set of columns.
  • Prefer cards or list items when each row has a different internal structure.
  • Keep column labels short and explicit so the header reads quickly.

Respect Numeric Alignment

  • Apply data-numeric="true" to both the header and cells of numeric columns.
  • Use tabular values for prices, counts, and percentages so totals stay visually aligned.
  • Avoid mixing freeform text into numeric columns unless the interface absolutely requires it.

Keep Row State Legible

  • Use data-state="selected" on TableRow when the row is actively selected.
  • Let hover and focus states support scanability rather than turn the table into a high-contrast grid.
  • If the surface needs filtering, bulk actions, or pagination, compose those controls around the table instead of inside the cells.

Use Striping Sparingly

  • Use striped on TableBody when longer datasets need extra scan support.
  • Use striped on TableHead and TableCell only for columns that genuinely benefit from a quieter band.
  • Do not stripe every row and every column at once. The table should still read through type, alignment, and shared edges first.

Keep Sticky Behavior Structural

  • Use sticky on TableHeader for the common sticky-header case.
  • Use sticky="left" or sticky="right" on TableHead and TableCell for pinned columns.
  • Add stickyOffset when more than one pinned column needs a measured offset.

API Reference

Exports

ExportRendersNotes
Tablewrapper div + tableAdds horizontal overflow handling and the outer border.
TableHeadertheadApplies the stronger bottom border rhythm for header rows.
TableBodytbodyRemoves the trailing row border on the last row and can stripe rows.
TableFootertfootAdds muted background treatment for summary rows.
TableRowtrIncludes hover, focus-within, and optional selected styling.
TableHeadthUppercase condensed header cell with optional numeric, striped, or sticky treatment.
TableCelltdDefault body cell spacing and text treatment with optional numeric, striped, or sticky treatment.
TableCaptioncaptionMuted caption copy below the table.

Repo-Specific Behaviors

PatternDetail
data-numeric="true"Right-aligns numbers and enables tabular alignment on TableHead and TableCell.
numericDirect boolean prop alternative for the same numeric alignment behavior.
data-state="selected"Applies the selected row background on TableRow.
focus within rowAdds the stronger inset border treatment while interactive content inside the row has focus.
stripedAvailable on TableBody, TableHead, and TableCell for row and column banding.
stickyAvailable on TableHeader, TableHead, and TableCell for sticky headers and pinned columns.
stickyOffsetSets the offset for pinned columns when more than one column is sticky on the same side.
surface, chrome, density, layoutAvailable on Table to tune surface tone, border strength, row density, and layout strategy.

All components accept the standard props for their underlying HTML elements plus className.