Skip to main content
astrocraft-ui/ components · 101

Table

Free · MIT

Headless, accessible, and styled entirely through the attribute surface below — bring your own CSS system, or start from the reference theme.

Install

Without a flag you get no styling at all — plain HTML carrying the attribute surface below. --theme copies the same theme in two dialects;--bridge lumos re-points either one onto Lumos for Astro's tokens (it needs a theme to re-point, and Lumos itself, already in your project).

Unstyled — behavior only, you write the CSS

Install command
npx astrocraft-ui add display/table

Plain-CSS theme — no build step

Install command
npx astrocraft-ui add display/table --theme css

Tailwind theme — needs Tailwind v4

Install command
npx astrocraft-ui add display/table --theme tailwind

Plain-CSS theme, re-pointed onto Lumos tokens

Install command
npx astrocraft-ui add display/table --theme css --bridge lumos

Tailwind theme, re-pointed onto Lumos tokens

Install command
npx astrocraft-ui add display/table --theme tailwind --bridge lumos

Live demo

Table

A list of recent invoices.
InvoiceStatusMethodAmount
INV-001PaidCredit Card$250.00
INV-002PendingPayPal$150.00
INV-003UnpaidBank Transfer$350.00
Total$750.00

Attribute surface

With no class-merging machinery, these attributes are the whole extension point. State is a data-attribute or a native attribute; visibility is the hiddenattribute. Generated from source by pnpm slots.

ComponentSlotsVariantsRuntime stateNative state
`Table.astro``table` `table-container`———
`TableBody.astro``table-body`———
`TableCaption.astro``table-caption`———
`TableCell.astro``table-cell`———
`TableFooter.astro``table-footer`———
`TableHead.astro``table-head`———
`TableHeader.astro``table-header`———
`TableRow.astro``table-row`———

Source

What the command copies — 9 files, alias-free so the copy lands standing alone. This is the whole component; there is nothing else.

src/components/ui/display/table/Table.astro
---
// src/components/ui/display/table/Table.astro — headless primitive (see ../../README.md).
// Static <table> in a wrapper meant to scroll horizontally. Compose TableHeader / TableBody /
// TableFooter / TableRow / TableHead / TableCell / TableCaption. (Sorting / data-grid behavior is out
// of scope.) The wrapper is the one place a theme should put `overflow-x: auto` — a table is the
// classic element that must be allowed to out-width its column while the page body never does.
import type { HTMLAttributes } from "astro/types";

type Props = HTMLAttributes<"table">;

const { class: className, ...rest } = Astro.props;
---

<div data-slot="table-container">
  <table class={className} data-slot="table" {...rest}>
    <slot />
  </table>
</div>
src/components/ui/display/table/TableBody.astro
---
// src/components/ui/display/table/TableBody.astro — Table compound part (see ../../README.md). Wraps <tbody>.
import type { HTMLAttributes } from "astro/types";

type Props = HTMLAttributes<"tbody">;

const { class: className, ...rest } = Astro.props;
---

<tbody class={className} data-slot="table-body" {...rest}><slot /></tbody>
src/components/ui/display/table/TableCaption.astro
---
// src/components/ui/display/table/TableCaption.astro — Table compound part (see ../../README.md). Wraps <caption>.
import type { HTMLAttributes } from "astro/types";

type Props = HTMLAttributes<"caption">;

const { class: className, ...rest } = Astro.props;
---

<caption class={className} data-slot="table-caption" {...rest}><slot /></caption>
src/components/ui/display/table/TableCell.astro
---
// src/components/ui/display/table/TableCell.astro — Table compound part (see ../../README.md). Wraps <td>.
import type { HTMLAttributes } from "astro/types";

type Props = HTMLAttributes<"td">;

const { class: className, ...rest } = Astro.props;
---

<td class={className} data-slot="table-cell" {...rest}><slot /></td>
src/components/ui/display/table/TableFooter.astro
---
// src/components/ui/display/table/TableFooter.astro — Table compound part (see ../../README.md). Wraps <tfoot>.
import type { HTMLAttributes } from "astro/types";

type Props = HTMLAttributes<"tfoot">;

const { class: className, ...rest } = Astro.props;
---

<tfoot class={className} data-slot="table-footer" {...rest}><slot /></tfoot>
src/components/ui/display/table/TableHead.astro
---
// src/components/ui/display/table/TableHead.astro — Table compound part (see ../../README.md). Wraps <th>; pass
// `scope="col"` / `scope="row"` through for assistive tech.
import type { HTMLAttributes } from "astro/types";

type Props = HTMLAttributes<"th">;

const { class: className, ...rest } = Astro.props;
---

<th class={className} data-slot="table-head" {...rest}><slot /></th>
src/components/ui/display/table/TableHeader.astro
---
// src/components/ui/display/table/TableHeader.astro — Table compound part (see ../../README.md). Wraps <thead>.
import type { HTMLAttributes } from "astro/types";

type Props = HTMLAttributes<"thead">;

const { class: className, ...rest } = Astro.props;
---

<thead class={className} data-slot="table-header" {...rest}><slot /></thead>
src/components/ui/display/table/TableRow.astro
---
// src/components/ui/display/table/TableRow.astro — Table compound part (see ../../README.md). Wraps <tr>.
import type { HTMLAttributes } from "astro/types";

type Props = HTMLAttributes<"tr">;

const { class: className, ...rest } = Astro.props;
---

<tr class={className} data-slot="table-row" {...rest}><slot /></tr>
src/components/ui/display/table/index.ts
import Table from "./Table.astro";
import TableBody from "./TableBody.astro";
import TableCaption from "./TableCaption.astro";
import TableCell from "./TableCell.astro";
import TableFooter from "./TableFooter.astro";
import TableHead from "./TableHead.astro";
import TableHeader from "./TableHeader.astro";
import TableRow from "./TableRow.astro";

export { Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow };
export default Table;

What you get

The component source, copied into your project by npx astrocraft-ui add display/table — no package dependency, no CSS to fight. Whatever the paid blocks compose, this is it.