Skip to content

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.

NameStatusActions
Order #123Active
Order #124Pending
Order #125Draft

data-density="compact" reduces vertical padding for data-dense lists.

<table class="hc-table" data-density="compact">
</table>

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 idlocal
Display nameLocal development
Created2026-06-01

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.

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.

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

  • 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: block on <table>, <thead>, or <tbody> for responsiveness; that breaks screen reader semantics. Wrap the table in a horizontally scrollable container instead.
Token pathPurpose
table.borderCell separator color.
table.fgBody text color.
table.font-sizeBody font size.
table.header-bgHeader row background.
table.header-fgHeader text color.
table.header-weightHeader font weight.
table.row-hover-bgRow hover background.
table.cell-padding-xInline cell padding.
table.cell-padding-yBlock cell padding.
table.kv-key-widthKey column width (data-variant="kv").
table.kv-key-fgKey text color (data-variant="kv").
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-fg
  • Badge — status indicators inside cells.
  • Status colors — the .hc-status utility for status-coloured cell text and row highlights (data-fill), theme-aware.
  • Button — row actions.