Skip to content
Zuno UI
Explore components
EXPLORE
Actions
Forms
Layout
Navigation
Data display
Feedback
Overlays
RESOURCES

Table

A semantic tabular base with consistent alignment and density; sorting, filtering and pagination belong to your data layer.

ProjectStatusBudget
Redesign 2026On track$12,400
Mobile appAt risk$18,250
Docs migrationPaused$1,000

Installation

Run it from the root of a project already set up with zunoui init.

npx zunoui@latest add table

Dependencies

What add table installs alongside the component. The CLI skips any you already have in a compatible version.

ZUNO registry

  • @zuno/utils

Examples

4 examples · 1 component
table
Active projects this quarter.
ProjectStatusBudget
Redesign 2026On track$12,400
Mobile appAt risk$18,250
Docs migrationPaused$1,000
Total$31,650

Caption and footer

Numeric columns end-aligned with tabular figures; the caption names the table.

table
EventUserTime
Project createdAna09:12
Member invitedLuis09:30
Budget updatedAna10:05
File uploadedMarta10:41

Compact density

density="compact" for dense data, inside a bordered wrapper.

table
Project
Redesign 2026
Mobile app
Docs migration

Row selection

Selection state lives in your code; data-state marks the row and each checkbox has a name.

table
ProjectOwnerBudget

No matching projects

Try a different search or clear the filters.

No results

One cell spanning every column holds an Empty state.

API reference

Forwards props and ref to the container element; it only adds composition utilities.

PropTypeDefault
density

Row height; compact for data-heavy contexts.

"comfortable" | "compact""comfortable"
containerProps

Props for the scroll wrapper: className (border, radius, max height), and tabIndex, role and aria-label for keyboard scrolling.

ComponentProps<"div">—
Table

Native table inside a horizontally scrollable wrapper.

table—
TableHeader / TableBody / TableFooter

Native row groups.

thead / tbody / tfoot—
TableRow

Row with hover; data-state="selected" highlights it.

tr—
TableHead

Header cell; add scope="row" for row headers.

th—
TableCell

Data cell.

td—
TableCaption

Accessible table name, shown below it.

caption—

States

The states that apply to this component and their visual treatment.

StateTreatment
HoverRows get a subtle muted background.
Selecteddata-state="selected" keeps the row highlighted; the checkbox conveys it without color.
Compactdensity="compact" reduces row height for dense data.
EmptyA single cell spanning every column holds an Empty state.
OverflowThe wrapper scrolls horizontally when the columns do not fit.

Accessibility

Native table semantics: screen readers announce rows, columns and headers without extra roles.

Give the table a name with TableCaption (or aria-label / aria-labelledby when the caption would be redundant).

Mark selection with data-state="selected" plus a checkbox with an accessible name; the highlight is not the only indicator.

The wrapper scrolls horizontally on narrow screens instead of breaking the layout. When a table can overflow and has no focusable content, pass containerProps={{ tabIndex: 0, role: "region", "aria-label": … }} so keyboard users can scroll it (Safari does not make scrollers focusable).

Headers and cells use logical alignment (text-start), so the table reads correctly in right-to-left layouts; end-align numeric columns and use tabular-nums.