Table
hc-table is a class applied to a standard <table>. Use proper
<thead> / <tbody> / <th scope="col"> / <td> structure so the
table is announceable to assistive tech.
Basic HTML
Section titled “Basic HTML”| Name | Status | Actions |
|---|---|---|
| Order #123 | Active | |
| Order #124 | Pending | |
| Order #125 | Draft |
<table class="hc-table"> <thead> <tr> <th scope="col">Name</th> <th scope="col">Status</th> <th scope="col">Actions</th> </tr> </thead> <tbody> <tr> <td>Order #123</td> <td><span class="hc-badge" data-variant="success">Active</span></td> <td><button class="hc-button" type="button" data-size="sm">View</button></td> </tr> <tr> <td>Order #124</td> <td><span class="hc-badge" data-variant="warning">Pending</span></td> <td><button class="hc-button" type="button" data-size="sm">View</button></td> </tr> <tr> <td>Order #125</td> <td><span class="hc-badge">Draft</span></td> <td><button class="hc-button" type="button" data-size="sm">View</button></td> </tr> </tbody></table>Density
Section titled “Density”data-density="compact" reduces vertical padding for data-dense lists.
| Name | Status |
|---|---|
| Order #123 | Active |
| Order #124 | Pending |
| Order #125 | Draft |
| Name | Status |
|---|---|
| Order #123 | Active |
| Order #124 | Pending |
| Order #125 | Draft |
<table class="hc-table" data-density="compact"> <thead> <tr><th scope="col">Name</th><th scope="col">Status</th></tr> </thead> <tbody> <tr><td>Order #123</td><td>Active</td></tr> <tr><td>Order #124</td><td>Pending</td></tr> <tr><td>Order #125</td><td>Draft</td></tr> </tbody></table>Numeric columns
Section titled “Numeric columns”Cells render digits as tabular figures
(font-variant-numeric: tabular-nums) by default, so runs of digits —
counts, amounts, timestamps — align vertically down a column. The
property affects digit glyphs only; text cells are unchanged.
Right-alignment is per-column semantics, so it is a declarative
opt-in: data-numeric on a cell or header cell end-aligns it
(text-align: end — logical, so RTL flips free).
| Item | Qty | Amount |
|---|---|---|
| Widget | 1,114 | 9,110.25 |
| Gadget | 98 | 101.09 |
| Gizmo | 7 | 1,987.50 |
<table class="hc-table"> <thead> <tr> <th scope="col">Item</th> <th scope="col" data-numeric>Qty</th> <th scope="col" data-numeric>Amount</th> </tr> </thead> <tbody> <tr><td>Widget</td><td data-numeric>1,114</td><td data-numeric>9,110.25</td></tr> <tr><td>Gadget</td><td data-numeric>98</td><td data-numeric>101.09</td></tr> <tr><td>Gizmo</td><td data-numeric>7</td><td data-numeric>1,987.50</td></tr> </tbody></table>Conditional formatting
Section titled “Conditional formatting”The server evaluates the rule and renders the outcome as
data-tone="info | success | warning | error" on a cell (td/th) or
a whole tr; the stylesheet tints it with the shared semantic status
colors (dark-theme aware). Don’t rely on the color alone — keep the
value or a text marker in the cell:
<tr> <td>Legacy sync</td> <td data-tone="error">Failed</td></tr>Key-value variant
Section titled “Key-value variant”data-variant="kv" turns the table into a two-column definition list
for detail views — keys are row headers on a fixed inline size with
muted text, values keep the body styling, and the row hover highlight
is off (nothing to act on):
| Realm id | local |
|---|---|
| Display name | Local development |
| Created | 2026-06-01 |
<table class="hc-table" data-variant="kv"> <tbody> <tr><th scope="row">Realm id</th><td>local</td></tr> <tr><th scope="row">Display name</th><td>Local development</td></tr> <tr><th scope="row">Created</th><td>2026-06-01</td></tr> </tbody></table>Override the key column width with --hc-table-kv-key-width
(default 10rem). Use <th scope="row"> for the keys — that is what
the variant styles, and it keeps the pairs announceable.
Responsive — horizontal scroll
Section titled “Responsive — horizontal scroll”A data table cannot shrink below the content width of its columns, so a
wide table on a narrow screen would otherwise push the whole page sideways.
Wrap it in .hc-table-scroll to confine the overflow to a scrollable strip.
Because the strip scrolls, it must be reachable by keyboard — make the
wrapper a focusable, labelled region (role="region", aria-label,
tabindex="0"):
<div class="hc-table-scroll" role="region" aria-label="Orders" tabindex="0"> <table class="hc-table"> … </table></div>On wide viewports the wrapper is invisible; it only scrolls once the table exceeds its width.
htmx usage
Section titled “htmx usage”For inline row updates, swap the <tr> itself.
<tr id="item-123"> <td>Order #123</td> <td><span class="hc-badge" data-variant="success">Active</span></td> <td> <button class="hc-button" type="button" data-variant="error" data-hc-confirm="Delete this item?" data-hx-delete="/items/123" data-hx-trigger="hc:confirmed" data-hx-target="closest tr" data-hx-swap="outerHTML"> Delete </button> </td></tr>This is the exact pattern from plan §24. See the confirm-action recipe.
Accessibility
Section titled “Accessibility”- Always provide
<thead>and<th scope="col">for column headers. When a row has a row header, use<th scope="row">on the first cell. - Wrap action buttons in cells with descriptive labels — avoid
icon-only buttons unless they include
aria-label. - For long tables, do not apply
display: blockon<table>,<thead>, or<tbody>for responsiveness; that breaks screen reader semantics. Wrap the table in a horizontally scrollable container instead.
Theming tokens
Section titled “Theming tokens”| Token path | Purpose |
|---|---|
table.border | Cell separator color. |
table.fg | Body text color. |
table.font-size | Body font size. |
table.header-bg | Header row background. |
table.header-fg | Header text color. |
table.header-weight | Header font weight. |
table.row-hover-bg | Row hover background. |
table.cell-padding-x | Inline cell padding. |
table.cell-padding-y | Block cell padding. |
table.kv-key-width | Key column width (data-variant="kv"). |
table.kv-key-fg | Key text color (data-variant="kv"). |
CSS variables
Section titled “CSS variables”Show the generated CSS variables
--hc-table-border | -fg | -font-size--hc-table-header-bg | -header-fg | -header-weight--hc-table-row-hover-bg--hc-table-cell-padding-x | -cell-padding-y--hc-table-kv-key-width | -kv-key-fgRelated
Section titled “Related”- Datagrid — when you need sorting, row selection, or keyboard navigation on top of a table.
- Badge — status indicators inside cells.
- Status colors — the
.hc-statusutility for status-coloured cell text and row highlights (data-fill), theme-aware. - Button — row actions.
Used in recipes: Chart