Menu
General
ButtonBadgePillsAvatarBrand lockupLayout
ContainerGrid & RowSurface & text utilitiesApp shellPage headerData Display
CardTableChartsCalendarStatsBulletsLeadersLogo wallCollapse & DisclosureTimelineValue chainDescriptionsFeedback
AlertProgressModalSlide-overSkeletonEmpty stateForms
Field & InputDropdownLead form & CTA rowDate pickerFilter barNavigation
NavSide navigationTop navigationApp switcherUser menuStepperTabsBreadcrumbPaginationTemplates
Sign-in pageSigned-out pageSettings layoutTheming
Browser tabProduct themesData Display
Table
Data-dense table: single-line cells in a scroll container, right-aligned numerals, end-aligned actions.
.table · .tablewrap · .cell--wrap · .cell--actions · .cell-stack
| Reference | Merchant | Product | Amount (USD) | Status | Submitted | Actions |
|---|---|---|---|---|---|---|
TXN-241099 | Hillcrest Grocers Makati | novapay | 151.17 | Status · Settled | 27 Aug 2026, 18:31 | |
TXN-241073 | Riverside Fuel Station 12 | novastore | 401.87 | Status · Pending | 27 Aug 2026, 17:57 | |
TXN-240981 | Harbourfront Pharmacy | novabank | 96.40 | Status · Failed | 27 Aug 2026, 15:12 |
<div class="card card--flush">
<div class="tablewrap">
<table class="table">
<thead><tr><th>Reference</th><th>Merchant</th><th>Product</th><th class="num">Amount (USD)</th><th>Status</th><th>Submitted</th><th class="cell--actions">Actions</th></tr></thead>
<tbody>
<tr><td><code>TXN-241099</code></td><td>Hillcrest Grocers Makati</td><td>novapay</td><td class="num">151.17</td><td><span class="badge badge--success"><span class="badge__dot"></span> Status · Settled</span></td><td>27 Aug 2026, 18:31</td><td class="cell--actions"><button class="btn btn--ghost btn--sm">Detail</button></td></tr>
<tr><td><code>TXN-241073</code></td><td>Riverside Fuel Station 12</td><td>novastore</td><td class="num">401.87</td><td><span class="badge badge--warning"><span class="badge__dot"></span> Status · Pending</span></td><td>27 Aug 2026, 17:57</td><td class="cell--actions"><button class="btn btn--ghost btn--sm">Detail</button></td></tr>
<tr><td><code>TXN-240981</code></td><td>Harbourfront Pharmacy</td><td>novabank</td><td class="num">96.40</td><td><span class="badge badge--danger"><span class="badge__dot"></span> Status · Failed</span></td><td>27 Aug 2026, 15:12</td><td class="cell--actions"><button class="btn btn--ghost btn--sm">Detail</button></td></tr>
</tbody>
</table>
</div>
</div>
| Holder | Terminal | Note |
|---|---|---|
Unclaimed | TRM-0128 | Two failed settlements in the last hour on the same terminal; review the device before the next batch window. |
ops.admin | TRM-0177 | Gateway certificate renewal scheduled. |
<div class="tablewrap">
<table class="table">
<thead><tr><th>Holder</th><th>Terminal</th><th>Note</th></tr></thead>
<tbody>
<tr><td><div class="cell-stack"><span>Unclaimed</span><span class="cell-stack__meta">Credit analyst</span></div></td><td><code>TRM-0128</code></td><td class="cell--wrap">Two failed settlements in the last hour on the same terminal; review the device before the next batch window.</td></tr>
<tr><td><div class="cell-stack"><span>ops.admin</span><span class="cell-stack__meta">Operations</span></div></td><td><code>TRM-0177</code></td><td class="cell--wrap">Gateway certificate renewal scheduled.</td></tr>
</tbody>
</table>
</div>
Usage
- Put every data table in a
.tablewrap: cells stay on one line and the table scrolls sideways inside its container instead of squeezing columns, so identifiers, names, chips, dates, and amounts never break across lines. The page itself never scrolls sideways. - Free-text columns opt back into wrapping with
.cell--wrap, which keeps a readable minimum width. - A second fact in a cell goes in a
.cell-stack: two single-line lines, the second one muted. - Numeric columns take
class="num"on the header and the cells (right-aligned, tabular numerals); row actions take.cell--actions, aligned to the end. - Header cells sit on the subtle tint; rows highlight on hover for scanning. See Alignment and content fit.
Popovers and menus in a table
The scroll wrap is a containing block, so anything absolutely positioned inside it is clipped by it. That is deliberate: it keeps visually hidden text from extending the page sideways on a phone. It also means a row menu, popover or tooltip must render outside the wrap rather than inside the cell it belongs to.
CSS
These rules ship in the console pattern layer, admin-kits/shared/novus-admin.css, which this site and every Admin Kit flavor load after tokens.css. Copy the whole layer, or only the sections below; every value is a token.
/* One short value, one line. Tables scroll inside .tablewrap instead of
squeezing; free text opts back into wrapping; fixed slots truncate. */
.badge, .filterchip, .quickchip, .crumbs li, .paginator__label, .listfooter__range, .nowrap { white-space: nowrap; }
.truncate { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Positioned so the wrap is the containing block for its own absolutely positioned
descendants. Without this, a .sr-only span inside a horizontally scrolled table
resolves against the initial containing block, escapes this clip, and extends the
document's scroll width: the page scrolls sideways on a phone while the table
looks correctly contained. A popover inside a scrolling table must therefore be
rendered outside the wrap, because it is now clipped by it. */
.tablewrap { position: relative; overflow-x: auto; overscroll-behavior-x: contain; }
.tablewrap table th, .tablewrap table td { white-space: nowrap; vertical-align: middle; }
.tablewrap table .cell--wrap { white-space: normal; min-width: 16rem; }
.table th.num, .table td.num { text-align: right; font-variant-numeric: tabular-nums; }
.table th.cell--actions, .table td.cell--actions { text-align: right; width: 1%; }
.cell--actions .btn + .btn { margin-inline-start: var(--space-2); }
.cell-stack { display: flex; flex-direction: column; gap: calc(var(--space-1) / 2); }
.cell-stack__meta { font-size: var(--text-xs); line-height: var(--lh-xs); color: var(--text-secondary); }
/* Portal text uses the width of its row: the kit's reading measure is for
prose, so console screens reset it. A measure is opted into explicitly
(constitution 1.12.0, Principle IV). */
.adminmain p, .adminmain li, .authcard p, .settings p, .signedout p, .chartcard p { max-width: none; }
.measure { max-width: 68ch; }