Skip to content
Dethink Components

ComponentsTable

Table

Display data in rows and columns.

On this page

Use this component from the local workspace package. Follow the setup guide first. A public npm package and registry are not available yet.

View registry files

Import the component into your page or component file.

Usage
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.

Recent releases and adoption.
VersionReleasedDownloads
1.4.0Jun 202612,410
1.3.2May 202631,876
1.3.1May 20268,204
Show sourceexamples/table/basic.tsx
examples/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.

compactp50p99
US East38 ms212 ms
EU West44 ms301 ms
comfortablep50p99
US East38 ms212 ms
EU West44 ms301 ms
Show sourceexamples/table/density.tsx
examples/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.

Invoice #2026-0714 — July 2026
ItemQtyUnitAmount
Team plan · 12 seats12$29.00$348.00
SSO add-on1$99.00$99.00
Usage overageper request41,000$0.00$32.80
Total due$479.80
Show sourceexamples/table/recipe-invoice.tsx
examples/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.

Table anatomy
PropWhat it doesDefault
Table — density"compact" | "default" | "comfortable"Row height and padding scale for the whole table."default"
Table — containerClassNamestringStyles 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 / hoverablebooleanSelected 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 | CaptionReal table elements underneath — semantics, keyboard behavior, and screen-reader navigation are native.Not set