ComponentsTable
Table
Display data in rows and columns.
On this page
Install component source from the public registry, or use the local workspace package. Follow the setup guide first. The npm package is not published yet.
View registry filesImplemented with React and browser APIs, without an additional behavior or rendering library.
Shared foundation: React, clsx for conditional classes, tailwind-merge for resolving utility-class conflicts. Styles use Tailwind CSS and Dethink CSS variables.
Based on this component’s source and registry composition. Libraries used only in showcase examples are excluded.
Import the component into your page or component file.
import {
Table,
TableBody,
TableCaption,
TableCell,
TableFooter,
TableHead,
TableHeader,
TableRow,
} from "@dethink/components";Try the examples, then open the code to use them in your app.
Basic
Caption, header, and body with an end-aligned numeric column.
| Version | Released | Downloads |
|---|---|---|
| 1.4.0 | Jun 2026 | 12,410 |
| 1.3.2 | May 2026 | 31,876 |
| 1.3.1 | May 2026 | 8,204 |
Show sourceexamples/table/basic.tsx
"use client";
import {
Table,
TableBody,
TableCaption,
TableCell,
TableHead,
TableHeader,
TableRow,
} from "@dethink/components";
const releases = [
{ version: "1.4.0", date: "Jun 2026", downloads: "12,410" },
{ version: "1.3.2", date: "May 2026", downloads: "31,876" },
{ version: "1.3.1", date: "May 2026", downloads: "8,204" },
];
export function TableBasic() {
return (
<Table>
<TableCaption>Recent releases and adoption.</TableCaption>
<TableHeader>
<TableRow>
<TableHead>Version</TableHead>
<TableHead>Released</TableHead>
<TableHead align="end">Downloads</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{releases.map((release) => (
<TableRow key={release.version}>
<TableCell className="font-mono">{release.version}</TableCell>
<TableCell>{release.date}</TableCell>
<TableCell align="end" className="tabular-nums">
{release.downloads}
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
);
}Density
compact for dashboards, comfortable for reading-heavy tables.
| compact | p50 | p99 |
|---|---|---|
| US East | 38 ms | 212 ms |
| EU West | 44 ms | 301 ms |
| comfortable | p50 | p99 |
|---|---|---|
| US East | 38 ms | 212 ms |
| EU West | 44 ms | 301 ms |
Show sourceexamples/table/density.tsx
"use client";
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from "@dethink/components";
const rows = [
{ region: "US East", p50: "38 ms", p99: "212 ms" },
{ region: "EU West", p50: "44 ms", p99: "301 ms" },
];
export function TableDensity() {
return (
<div className="grid gap-6 lg:grid-cols-2">
{(["compact", "comfortable"] as const).map((density) => (
<Table key={density} density={density}>
<TableHeader>
<TableRow>
<TableHead>{density}</TableHead>
<TableHead align="end">p50</TableHead>
<TableHead align="end">p99</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{rows.map((row) => (
<TableRow key={row.region}>
<TableCell>{row.region}</TableCell>
<TableCell align="end" className="tabular-nums">
{row.p50}
</TableCell>
<TableCell align="end" className="tabular-nums">
{row.p99}
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
))}
</div>
);
}Examples that combine components for common tasks.
Invoice
Numeric columns right-aligned with tabular numerals, a muted tone for the secondary usage line, and the computed total in a real TableFooter.
| Item | Qty | Unit | Amount |
|---|---|---|---|
| Team plan · 12 seats | 12 | $29.00 | $348.00 |
| SSO add-on | 1 | $99.00 | $99.00 |
| Usage overageper request | 41,000 | $0.00 | $32.80 |
| Total due | $479.80 | ||
Show sourceexamples/table/recipe-invoice.tsx
"use client";
import {
Table,
TableBody,
TableCaption,
TableCell,
TableFooter,
TableHead,
TableHeader,
TableRow,
} from "@dethink/components";
const lines = [
{ item: "Team plan · 12 seats", qty: 12, unit: 29, note: "" },
{ item: "SSO add-on", qty: 1, unit: 99, note: "" },
{
item: "Usage overage",
qty: 41_000,
unit: 0.0008,
note: "per request",
muted: true,
},
];
const currency = new Intl.NumberFormat("en-US", {
style: "currency",
currency: "USD",
});
/**
* Semantic table anatomy carrying real invoice structure: numeric columns
* right-aligned with tabular numerals, a muted tone for secondary lines,
* and the total in a real TableFooter.
*/
export function TableRecipeInvoice() {
const total = lines.reduce((sum, line) => sum + line.qty * line.unit, 0);
return (
<Table>
<TableCaption placement="top">
Invoice #2026-0714 — July 2026
</TableCaption>
<TableHeader>
<TableRow>
<TableHead>Item</TableHead>
<TableHead align="end">Qty</TableHead>
<TableHead align="end">Unit</TableHead>
<TableHead align="end">Amount</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{lines.map((line) => (
<TableRow key={line.item} tone={line.muted ? "muted" : "default"}>
<TableCell>
{line.item}
{line.note ? (
<span className="text-muted-foreground ml-2 text-xs">
{line.note}
</span>
) : null}
</TableCell>
<TableCell align="end" className="tabular-nums">
{line.qty.toLocaleString("en-US")}
</TableCell>
<TableCell align="end" className="tabular-nums">
{currency.format(line.unit)}
</TableCell>
<TableCell align="end" className="tabular-nums">
{currency.format(line.qty * line.unit)}
</TableCell>
</TableRow>
))}
</TableBody>
<TableFooter>
<TableRow>
<TableCell colSpan={3} className="font-medium">
Total due
</TableCell>
<TableCell align="end" className="font-medium tabular-nums">
{currency.format(total)}
</TableCell>
</TableRow>
</TableFooter>
</Table>
);
}Every part renders its native table element, so standard table attributes apply throughout.
| Prop | What it does | Default |
|---|---|---|
Table — density"compact" | "default" | "comfortable" | Row height and padding scale for the whole table. | "default" |
Table — containerClassNamestring | Styles the scroll container that keeps wide tables from breaking the page. | Not set |
TableHead / TableCell — align"start" | "center" | "end" | Column alignment; use end for numeric columns. | "start" |
TableRow — tone"default" | "muted" | Muted background for secondary rows. | "default" |
TableRow — selected / hoverableboolean | Selected background and hover treatment via data attributes. | Not set |
TableCaption — placement"top" | "bottom" | Where the caption renders; it names the table either way. | "bottom" |
AnatomyHeader | Body | Footer | Row | Head | Cell | Caption | Real table elements underneath — semantics, keyboard behavior, and screen-reader navigation are native. | Not set |