TableVirtual

June 13, 2026 · View on GitHub

A windowed table for large datasets (>500 rows). <kp-table> + <kp-virtual-list> baked together so you don't wire virtualization by hand: a sticky header over a virtualized body, only the visible rows in the DOM.

Contract

<kp-table-virtual> renders a sticky header row above a <kp-virtual-list> of data rows. Header and rows share one CSS grid template, so columns line up — give each column a width (any CSS length) or they share 1fr. Row height is fixed ([rowHeight], no per-row measurement) which is what keeps scrolling cheap.

For small, fully-rendered tables (sort, selection, <500 rows) use <kp-table>. This component is purpose-built for the long-list case and intentionally omits sort/selection — compose those over your data.

Inputs

InputTypeDefaultNotes
columnsKpTableColumn<T>[][]Reuses Table's column model (id · label · width? · align? · accessor?).
dataT[][]The full dataset — only the visible window is rendered.
rowHeightnumber48Fixed px height per row.
viewportHeightnumber480Height of the scrolling body.
size'sm' | 'md' | 'lg''md'Padding + font ramp.
striped / borderedbooleanfalseVisual variants matching <kp-table>.
overscannumber4Extra rows rendered above/below the viewport.
trackBy(i, item) => unknown | nullnullIdentity for efficient re-render.
ariaLabelstring | nullnullAccessible name for the list.

Outputs

OutputPayloadWhen
(rowClick)TA row is clicked.

Cells

Plain columns render accessor(row). For rich cells (badges, links), project a per-column template:

<kp-table-virtual [columns]="cols" [data]="rows" ariaLabel="Users">
  <ng-template kpVirtualTableCell="status" let-row>
    <kp-badge size="sm" appearance="subtle" [color]="tone(row.status)">{{ row.status }}</kp-badge>
  </ng-template>
</kp-table-virtual>

Accessibility

Semantics mirror <kp-virtual-list> — a labelled list of rows (role="list"/listitem with aria-setsize/aria-posinset), not a role="grid". ARIA grid semantics over a windowed (partially-rendered) set aren't sound, so a labelled list is the honest, screen-reader-correct choice. Give it an [ariaLabel]. Keyboard: the viewport is focusable and scrolls with Arrow / PageUp/Down / Home/End.