Table
Styled HTML table primitives (Table / TableHeader / TableBody / TableRow / TableHead / TableCell / TableCaption / TableFooter). Low-level building blocks — use DataTable for sorting/filtering/pagination.
| 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 |
| Total | $1,200.00 | ||
Installation
pnpm dlx @hex-core/cli add tableWith sortable header
Column header is a ghost Button + chevron — wire onClick to your sort state in the parent. aria-sort exposes direction to screen readers.
<Table>
<TableCaption>Click a column header to sort.</TableCaption>
<TableHeader>
<TableRow>
<TableHead aria-sort="ascending">
<Button variant="ghost" size="sm" className="-ml-3 h-8 data-[state=open]:bg-accent">
Invoice
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
className="ml-2 h-3.5 w-3.5"
aria-hidden="true"
>
<path d="m18 15-6-6-6 6" />
</svg>
</Button>
</TableHead>
<TableHead>Status</TableHead>
<TableHead className="text-right">Amount</TableHead>
</TableRow>
</TableHeader>
<TableBody>
<TableRow>
<TableCell className="font-medium">INV001</TableCell>
<TableCell>Paid</TableCell>
<TableCell className="text-right">$250.00</TableCell>
</TableRow>
<TableRow>
<TableCell className="font-medium">INV002</TableCell>
<TableCell>Pending</TableCell>
<TableCell className="text-right">$1,200.00</TableCell>
</TableRow>
</TableBody>
</Table>With selection column
Leading checkbox column for bulk-action data grids — header checkbox toggles select-all; per-row checkboxes wire to your selection state. Skip the data-table primitive when you only need static rows.
<Table>
<TableHeader>
<TableRow>
<TableHead className="w-12">
<Checkbox aria-label="Select all rows" />
</TableHead>
<TableHead>Invoice</TableHead>
<TableHead>Status</TableHead>
<TableHead className="text-right">Amount</TableHead>
</TableRow>
</TableHeader>
<TableBody>
<TableRow data-state="selected">
<TableCell>
<Checkbox checked aria-label="Select INV001" />
</TableCell>
<TableCell className="font-medium">INV001</TableCell>
<TableCell>Paid</TableCell>
<TableCell className="text-right">$250.00</TableCell>
</TableRow>
<TableRow>
<TableCell>
<Checkbox aria-label="Select INV002" />
</TableCell>
<TableCell className="font-medium">INV002</TableCell>
<TableCell>Pending</TableCell>
<TableCell className="text-right">$1,200.00</TableCell>
</TableRow>
</TableBody>
</Table>API Reference
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | — | Additional CSS classes on the <table> |
AI Guidance
When to use
Use for simple tabular data where you render rows manually: invoice lists, pricing rows, settings tables. Responsive container wraps the <table> to allow horizontal scroll on small screens.
When not to use
Don't use for large datasets that need sorting/filtering/pagination (use DataTable). Don't use for layout (use CSS grid/flex). Don't use for <form> field arrays (use native fields).
Common mistakes
- Using <div> grids instead of a real <table> for tabular data (breaks a11y)
- Putting interactive controls in headers without keyboard semantics
- Missing TableCaption when the table has no other label
Accessibility
Semantic <table> / <thead> / <tbody> is used, so screen readers announce rows/columns. Include a TableCaption or aria-label. Mark column sort buttons with aria-sort.
Related components
Token budget: 450
Verified against @hex-core/components@1.12.0