Table
One bordered, rounded surface for tabular data, so every table reads the same. The header sits on a raised band above the canvas, rows divide with hairlines, and cells are start-aligned for RTL by construction.
Basic
Compose a table from its parts — Table.Root is the framed <table>, Table.Header / Table.Body wrap the <thead> / <tbody>, and Table.Row / Table.Head / Table.Cell are the <tr> / <th> / <td>. Give each Table.Head a scope="col" so the column headers are named for assistive tech.
| Surface | Token | Use |
|---|---|---|
| Canvas | bg-background | The base page background |
| Card | bg-surface | Panels raised off the canvas |
| Well | bg-sunken | Recessed insets and sidebars |
import { Table } from "@stridge/noctis";
const ROWS = [
{ surface: "Canvas", token: "bg-background", use: "The base page background" },
{ surface: "Card", token: "bg-surface", use: "Panels raised off the canvas" },
{ surface: "Well", token: "bg-sunken", use: "Recessed insets and sidebars" },
];
export default function TableBasic() {
return (
<Table.Root>
<Table.Header>
<Table.Row>
<Table.Head scope="col">Surface</Table.Head>
<Table.Head scope="col">Token</Table.Head>
<Table.Head scope="col">Use</Table.Head>
</Table.Row>
</Table.Header>
<Table.Body>
{ROWS.map((row) => (
<Table.Row key={row.token}>
<Table.Cell>{row.surface}</Table.Cell>
<Table.Cell className="font-mono text-foreground">{row.token}</Table.Cell>
<Table.Cell>{row.use}</Table.Cell>
</Table.Row>
))}
</Table.Body>
</Table.Root>
);
}
Escape hatch
Each part carries a .props() static (D12) returning a spreadable { "data-slot", className } bag, so you can style a plain semantic element as that part — useful when a <table> is generated by markdown or a foreign renderer. Spread Table.Cell.props() onto a <td> and it picks up the cell styling without the wrapper component.
| Key | Action |
|---|---|
| Enter | Confirm the selection |
| Esc | Dismiss the panel |
"use client";
import { Table } from "@stridge/noctis";
const ROWS = [
{ key: "Enter", action: "Confirm the selection" },
{ key: "Esc", action: "Dismiss the panel" },
];
export default function TableEscapeHatch() {
return (
<table {...Table.Root.props()}>
<thead {...Table.Header.props()}>
<tr {...Table.Row.props()}>
<th scope="col" {...Table.Head.props()}>
Key
</th>
<th scope="col" {...Table.Head.props()}>
Action
</th>
</tr>
</thead>
<tbody {...Table.Body.props()}>
{ROWS.map((row) => (
<tr key={row.key} {...Table.Row.props()}>
<td {...Table.Cell.props()} className="font-mono text-foreground">
{row.key}
</td>
<td {...Table.Cell.props()}>{row.action}</td>
</tr>
))}
</tbody>
</table>
);
}
Anatomy
Compose a table from its parts. Table carries no behaviour of its own — sort, select, and paginate are the caller's to add around these parts.
Table.Root— the bordered, rounded card wrapping the semantic<table>.classNamestyles the outer card (use it for call-site margins).Table.Header+Table.Body— the<thead>and<tbody>. The header reads as a raised band; the body flushes its last row's divider into the frame so the bottom border isn't doubled.Table.Row— one<tr>, drawing a hairline divider beneath it.Table.Head— a header<th>: quiet, medium-weight, and start-aligned over the browser's centered default.Table.Cell— a body<td>: start-aligned and top-aligned so multi-line cells read against single-line ones.
Each part stamps a single data-slot (noctis-table, noctis-table-header, noctis-table-body, noctis-table-row, noctis-table-head, noctis-table-cell) — the anchor table.css keys off — and forwards className verbatim (no class merging).
On surfaces
The same control re-tuned across the elevation scopes — the root canvas, an elevated panel, a menu, and a sunken well. It stays legible on every layer.
| Surface | Token |
|---|---|
| Canvas | bg-background |
| Card | bg-surface |
| Well | bg-sunken |
| Surface | Token |
|---|---|
| Canvas | bg-background |
| Card | bg-surface |
| Well | bg-sunken |
| Surface | Token |
|---|---|
| Canvas | bg-background |
| Card | bg-surface |
| Well | bg-sunken |
| Surface | Token |
|---|---|
| Canvas | bg-background |
| Card | bg-surface |
| Well | bg-sunken |
Design tokens
Generated from the component's declaration — the same graph that mints the CSS, so a variable name or its resolution default can't drift. The minted tokens are the public override seam: set one on any ancestor and every table in that region retunes — e.g. .report { --noctis-table-cell-padding-block: 1rem; } loosens every row's vertical rhythm beneath it. Knobs that aren't minted are reached through the part's data-slot. See Customization for the full override ladder and Tokens for the whole graph.
API reference
Generated from the component's types — every prop, type, default, and description comes straight from the source. Each part forwards the native attributes of its underlying table element alongside className; expand a row for the full type and description.