← Components

Data Table

DataTableComponent (columns: slot/array, rows: enumerable, row_href: proc, selectable: bool, paginated: bool). There's no trailing actions column: the first column's title is a link that's also the row's default "open" action, and the whole row is clickable to the same destination (<tr onclick> in this mockup; a real implementation would use a Stimulus controller or wrap the row in JS-free progressive enhancement). Statuses use Status Badge; taxonomy uses Pill; percentages use Meter.

.data-table-panel is the outer card: it owns the border/radius/shadow once, and holds the bulk-actions bar (hidden until a row is checked), the scrollable table, and the paginator as plain edge-to-edge children with internal dividers between them — not three separately-bordered pieces stacked and faked into looking attached.

0 selected
Order Category Status Margin Total
#48213: J. Alvarez Jul 10, 2026
Software Fulfilled
24.6%
$128.00
#48214: M. Chen Jul 10, 2026
Accessories Awaiting review
7.1% low
$64.50
#48215: S. Okafor Jul 9, 2026
Apparel Chargeback
16.0%
$212.99

Paginator: multi-page state

The single-page example above never shows page 2+ or .paginator__ellipsis in context — this demonstrates both, standalone (not attached to a .data-table-panel, since it's illustrating the paginator alone).

Usage guidance: leading column combines a thumbnail/icon swatch with a linked title + meta (.row-identity, .row-identity__title as an <a>) instead of bare text and a separate actions column. Any link inside a later column (e.g. a related-record reference) should call event.stopPropagation() so it doesn't also trigger the row's default navigation — the row-selection checkbox does the same. Right-align numeric columns (.is-numeric), and use Status Badge for state and Pill for taxonomy: never both on the same concept. Selection is optional per table (only add .data-table__select-col + bulk-select.js when there's a real bulk action); pagination is expected on every real listing.