Table
A responsive table component.
When to Use
Use Table when you need to:
- Display structured data in rows and columns (invoices, users, products)
- Show comparison data where users scan across multiple attributes
- Present tabular data with optional footer summaries or totals
- Render read-only data sets that benefit from aligned columns
- Build the presentation layer for more complex data table features
When Not to Use
- Sortable, filterable, or paginated data - use Data Table with TanStack Table
- Key-value pair display - use a description list or Card layout
- Page layout purposes - use CSS Grid or Flexbox instead of table elements
- Single-column lists - use a standard list or Item component
Invoice Table
Full-featured table with header, body, footer, and caption.
| Invoice | Status | Method | Amount |
|---|---|---|---|
| INV001 | Paid | Credit Card | $250.00 |
| INV002 | Pending | PayPal | $150.00 |
| INV003 | Unpaid | Bank Transfer | $350.00 |
| INV004 | Paid | Credit Card | $450.00 |
| INV005 | Paid | PayPal | $550.00 |
| INV006 | Pending | Bank Transfer | $200.00 |
| INV007 | Unpaid | Credit Card | $300.00 |
| Total | $2,250.00 | ||
Simple
Basic table with header and body rows.
| Name | Role | |
|---|---|---|
| John Doe | john@example.com | Admin |
| Jane Smith | jane@example.com | Editor |
| Bob Wilson | bob@example.com | Viewer |
With Status Badges
Table displaying status and priority using Badge components.
| Task | Status | Priority | Due Date |
|---|---|---|---|
| Design review | Completed | High | 2024-01-15 |
| Code implementation | In Progress | Medium | 2024-01-20 |
| Documentation | Pending | Low | 2024-01-25 |
Striped Rows
Alternating row backgrounds for improved readability using bg-muted/50.
| Product | Category | Stock | Price |
|---|---|---|---|
| Laptop Pro | Electronics | 45 | $1,299.00 |
| Wireless Mouse | Accessories | 120 | $49.99 |
| USB-C Hub | Accessories | 78 | $89.99 |
| Monitor 27" | Electronics | 32 | $449.00 |
| Keyboard | Accessories | 95 | $129.00 |
With Actions
Table rows with dropdown action menus for contextual operations.
| Customer | Status | Actions | |
|---|---|---|---|
| Alice Johnson | alice@example.com | Active | |
| Michael Chen | michael@example.com | Pending | |
| Sarah Davis | sarah@example.com | Inactive |
UX & Design Guidelines
Visual Hierarchy
Use TableHead with font-medium to clearly distinguish headers from data rows. Apply text-right to numeric columns (amounts, quantities) for easier scanning. Use font-medium on the primary identifier cell in each row (e.g., invoice number, name).
Spacing & Layout
Table cells use p-2 padding by default. Set explicit widths on header cells (className="w-[100px]") to prevent column shifting during data updates. The table container provides overflow-x-auto for horizontal scrolling on smaller viewports. Wrap the table in a rounded-lg border border-border container for a polished appearance.
Responsive Behavior
The Table component automatically enables horizontal scrolling when content overflows. On mobile, consider hiding less critical columns with className="hidden md:table-cell". For narrow screens, evaluate whether a list-based layout (using Card) would provide a better reading experience.
Color & Contrast
Row hover state uses hover:bg-muted/50 for subtle feedback. Selected rows use data-[state=selected]:bg-muted for clear visual indication. The footer uses bg-muted/50 to visually separate summary rows from data. Ensure all text content meets WCAG 2.1 AA contrast ratios against both default and striped row backgrounds.
Accessibility
Keyboard Navigation
- Tab — Move focus to the next interactive element within the table (links, buttons, checkboxes)
- Shift + Tab — Move focus to the previous interactive element
- Enter or Space — Activate focused buttons or checkboxes within cells
- Arrow Keys — Navigate within dropdown menus triggered from action cells
Screen Reader Support
- Use
TableCaptionto provide a descriptive summary of the table content - Add
scope="col"on column headers andscope="row"on row headers for complex tables - Screen readers announce the table structure (rows and columns) and navigate cell-by-cell
- Avoid using
aria-hiddenon cells that contain meaningful data
Sortable Columns
- Use
aria-sort="ascending"oraria-sort="descending"on sortable column headers - Provide a visual sort indicator (arrow icon) that matches the
aria-sortvalue - Announce sort changes to assistive technology using an
aria-liveregion
Selection States
When rows are selectable, use role="checkbox" with aria-checked on selection controls. The data-state="selected" attribute provides visual feedback while the checkbox communicates state to assistive technology. Use a "Select all" checkbox in the header with aria-label="Select all rows".
ARIA Attributes
{/* Always provide a caption for screen readers */}
<Table>
<TableCaption>Monthly revenue by product line.</TableCaption>
<TableHeader>
<TableRow>
<TableHead scope="col">Product</TableHead>
<TableHead scope="col">Revenue</TableHead>
</TableRow>
</TableHeader>
<TableBody>...</TableBody>
</Table>
{/* Sortable column headers */}
<TableHead
scope="col"
aria-sort={sortDir === "asc" ? "ascending" : "descending"}
>
<Button variant="ghost" onClick={toggleSort}>
Name <ArrowUpDown className="ml-2 size-4" />
</Button>
</TableHead>
{/* Row headers for two-dimensional data */}
<TableRow>
<TableHead scope="row">Q1 2024</TableHead>
<TableCell>$12,400</TableCell>
<TableCell>$9,800</TableCell>
</TableRow>Related Components
Data Table
Powerful table with sorting, filtering, pagination, and row selection via TanStack Table.
Card
Alternative for displaying records on mobile or when a table layout is too dense.
Pagination
Page navigation controls to pair with tables that have many rows.
Badge
Status indicators and labels commonly used within table cells.
API Reference
The Table component is composed of eight sub-components. Each accepts standard HTML attributes in addition to the props listed below.
Table
The root container, wrapped in a scrollable div for responsive overflow.
| Prop | Type | Default | Description |
|---|---|---|---|
| className | string | — | Additional CSS classes for the table element. |
| children | ReactNode | — | Table content (TableHeader, TableBody, TableFooter, TableCaption). |
TableHeader
The thead element. Child rows receive a bottom border.
| Prop | Type | Default | Description |
|---|---|---|---|
| className | string | — | Additional CSS classes for the thead element. |
TableBody
The tbody element. The last row's bottom border is removed.
| Prop | Type | Default | Description |
|---|---|---|---|
| className | string | — | Additional CSS classes for the tbody element. |
TableFooter
The tfoot element with a muted background and top border for summary rows.
| Prop | Type | Default | Description |
|---|---|---|---|
| className | string | — | Additional CSS classes for the tfoot element. Renders with a muted background. |
TableRow
A table row with hover and selected state styling.
| Prop | Type | Default | Description |
|---|---|---|---|
| className | string | — | Additional CSS classes for the row. |
| data-state | "selected" | — | When set to 'selected', applies highlighted row styles via bg-muted. |
TableHead
A header cell (th) with medium font weight and left alignment.
| Prop | Type | Default | Description |
|---|---|---|---|
| className | string | — | Additional CSS classes for the header cell. |
| scope | "col" | "row" | — | Specifies whether the header is for a column or row (improves accessibility). |
TableCell
A standard data cell (td) with consistent padding and alignment.
| Prop | Type | Default | Description |
|---|---|---|---|
| className | string | — | Additional CSS classes for the cell. |
| colSpan | number | 1 | Number of columns the cell should span. |
TableCaption
A caption element rendered below the table for descriptive context.
| Prop | Type | Default | Description |
|---|---|---|---|
| className | string | — | Additional CSS classes for the caption element. |
| children | ReactNode | — | Descriptive text for the table, rendered below the table body. |