Content & Data
Table
Table is a native HTML table foundation with captions, headers, body rows, footers, cell alignment, responsive overflow, RTL support, print-friendly scrolling, and composition patterns for empty/loading/error — not the interactive Data Table pattern (no sorting, selection, or pagination).
Compound semantic foundation — no density/sort/selection variants in Beta
- React last updated
- 2026-07-13
- Documentation last updated
- 2026-07-13
- Accessibility target
- WCAG 2.2 AA (target)
- Version
- 0.1.1-beta
Known open questions
- Figma component-set node ID unresolved — live MCP verification pending.
- Temporary table geometry and scroll-shadow tokens await Figma confirmation.
- Data Table (implemented 2026-07-15) composes Table for the narrow MVP scope approved 2026-07-13 — sorting only, external Pagination; selection, sticky headers, and density remain excluded from v1.
Live preview
Table is a native HTML foundation. It does not sort, select, paginate, or fetch data — compose those patterns separately, or wait for Data Table (sorting-only MVP scope approved, not yet implemented).
Projects
| Project | Owner | Status | Updated | Budget | Actions |
|---|---|---|---|---|---|
| Atlas | Usman Farooqi | Active | 11 Jul 2026 | $24,000 | |
| North Star | Maya Chen | Beta | 8 Jul 2026 | $18,500 | |
| Harbor Analytics with a long project title for overflow | Jordan Lee | Paused | 2 Jul 2026 | $9,250 | |
| Total | $51,750 | ||||
Screen-reader caption
Keep a native caption even when it is visually hidden. Prefer caption over duplicating the same text as aria-label on the table.
Visually hidden caption remains accessible
| Category | Amount |
|---|---|
| Design systems | $12,000 |
| Documentation | $4,500 |
Multi-level headers
Native colSpan, rowSpan, id, and headers attributes pass through — no column-definition API on Table.
Grouped metrics
| Project | Financials | Actions | |
|---|---|---|---|
| Budget | Spend | ||
| Atlas | $24,000 | $19,400 | |
Interactive cells
Compose Checkbox, Link, Badge, and Menu inside cells. The row stays a non-interactive tr.
Review queue
| Select | Item | Status | Actions |
|---|---|---|---|
| Atlas | Needs review |
Empty, loading, and error composition
Table has no empty, loading, or error props. Compose Empty State, Skeleton, and Alert with full-width cells and keep headers when useful.
Empty
| Project | Owner | Budget |
|---|---|---|
No archived projectsArchived work will appear here once a project is moved out of the active set. | ||
Loading
| Project | Owner | Budget |
|---|---|---|
Error
Could not refresh projects
The table below shows the last successful snapshot. Retry remains consumer-owned.
| Project | Budget |
|---|---|
| Atlas | $24,000 |
RTL sample
Alignment uses logical start/end. Horizontal overflow and edge fades follow writing direction.
dir=rtl
| المشروع | الميزانية | الإجراءات |
|---|---|---|
| Atlas | $24,000 |
Shape and surface smoke
Container radius follows shape tokens
| Token | Value |
|---|---|
| Radius | Container-capped — not a capsule |
Glass surface
| Surface | Note |
|---|---|
| Glass | Header and footer remain distinct |
| Footer | Uses footer surface alias |
Purpose
Anatomy
Variants and states
When to use
When not to use
Accessibility
Keyboard behavior
Common mistakes
Properties
What is the difference between Table and Data Table?
Why does Table use native HTML?
Does Table use role="grid"?
When should a table include a caption?
How should row headers be marked?
Can cells contain buttons and links?
How does Table work on mobile?
Does Table support sorting?
Does Table support row selection?
When should a true ARIA Grid be used?
Tokens used
Known limitation
Component API
| Prop | Type | Default | Description |
|---|---|---|---|
| layout | "auto" | "fixed" | "auto" | Table layout algorithm. |
| TableCaption.visibility | "visible" | "screen-reader" | "visible" | Caption visibility while remaining accessible. |
| TableHead.align / TableCell.align | "start" | "center" | "end" | "start" | Logical text alignment via CSS — not HTML align. |
| TableScrollArea.accessibleLabel | string | — | Names the overflow region when horizontal scrolling needs a landmark. Keep distinct from the caption. |
| TableScrollArea.tabIndex | number | — | Consumer-controlled. Recommend 0 for known horizontally scrollable tables; omit when the table fits. |
| data-table-wrap | "nowrap" | — | Optional attribute on TableHead/TableCell to prevent wrapping (action columns). |
React example
import {
Table,
TableBody,
TableCaption,
TableCell,
TableHead,
TableHeader,
TableRow,
TableScrollArea,
} from "@/components/ui/Table";
export function Example() {
return (
<TableScrollArea accessibleLabel="Scrollable projects table" tabIndex={0}>
<Table>
<TableCaption>Active projects</TableCaption>
<TableHeader>
<TableRow>
<TableHead scope="col">Project</TableHead>
<TableHead scope="col" align="end">
Budget
</TableHead>
</TableRow>
</TableHeader>
<TableBody>
<TableRow>
<TableHead scope="row">Atlas</TableHead>
<TableCell align="end">$24,000</TableCell>
</TableRow>
</TableBody>
</Table>
</TableScrollArea>
);
}Related components
- List Item — single-column rows, not multi-column tables
- Badge — status metadata inside cells
- Link — navigational cell content
- Menu — row actions inside cells
- Checkbox — selection controls inside cells (composition only)
- Empty State — compose manually when a table has no rows
- Skeleton — loading placeholder rows
- Alert — error messaging above or beside tables
- Pagination — external composition for paged data