Krizaka
Documentation

Data table

A table of records — sort, selection, loading, empty and error states — that turns into cards on a phone and renders only the rows in view when there are thousands.

WebBêtaAffichage de données

Web uniquement — React, depuis @krizaka/ui/data-table. Bêta : son API peut encore changer à une version mineure.

Quand l’utiliser

  • To compare records on the same columns: jobs, videos of a studio, users of an admin, invoices.
  • When people sort, select several rows for a bulk action, or scan a status column.
  • With virtualize for a long list loaded at once (logs, 5,000 events) that must stay smooth.

Quand ne pas l’utiliser

  • For a few figures side by side: stats.À la place : Stat
  • For a gallery of media where the picture matters more than the columns: a grid of cards.À la place : Card

Installation

Installer

npm install @krizaka/ui @krizaka/tailwind @krizaka/tokens tailwindcss

Styles

@import "tailwindcss";
@import "@krizaka/tailwind";
@import "@krizaka/ui/tailwind.css";

Importer

import { DataTable } from "@krizaka/ui/data-table";

Exemples

Jobs

Sortable columns, a status badge, row selection for a bulk action.

Jobs
Status
Podcast transcriptWhisper largerunning318 s
Catalogue summariesLlama 3.3done96 s
Product shots, autumnFlux 1.1done42 s
Trailer voice-overXTTS v2failed7 s

Cards on a phone

layout="cards": each row a card, the title on top — what auto does in a narrow container.

Your videos
TitleVisibilityViewsTips
Sunset over MontréalPublic12,840$184.00
Behind the scenes, part 2Followers3,120$62.50

Loading

Skeleton rows while the first page loads, the table busy.

Users — Loading
UserRoleJoined

Empty

No record yet: an empty state with the next step.

Invoices
InvoiceAmount

No invoice yet

Your first invoice appears after your first payout.

Error

The request failed: an alert with a retry, in place of the rows.

Audit log
EventAt

The audit log could not be loaded.

5,000 rows

virtualize: only the rows in view are rendered, the header stays.

Events
At
evt-1view2026-10-01 00:00
evt-2tip2026-10-02 01:00
evt-3follow2026-10-03 02:00
evt-4comment2026-10-04 03:00
evt-5view2026-10-05 04:00
evt-6tip2026-10-06 05:00
evt-7follow2026-10-07 06:00
evt-8comment2026-10-08 07:00
evt-9view2026-10-09 08:00
evt-10tip2026-10-10 09:00
evt-11follow2026-10-11 10:00
evt-12comment2026-10-01 11:00
evt-13view2026-10-02 12:00
evt-14tip2026-10-03 13:00

Props

A table of records: sort, selection, loading / empty / error, cards on a phone, windowing for long lists.

PropTypeDéfautDescription
captionrequisstring—What the table lists ("Jobs", "Your videos"): its <caption>, hidden unless showCaption.
columnsrequisreadonly DataTableColumn<T>[]—The columns, in order.
getRowIdrequis(row: T) => string—A stable id per row: the React key and the selection's value.
rowsrequisreadonly T[]—The rows, in the order the server gave (sorted here unless manualSort).
classNamestring—Classes merged on the root.
defaultSelectedreadonly string[][]The ids selected at first, uncontrolled.
defaultSortDataTableSortnullThe sort at first, uncontrolled.
density"comfortable" | "compact"—comfortable (default) · compact.
emptyReactNode—Shown when there is no row (an EmptyState). Default: labels.empty.
errorReactNode—A failure, shown in place of the rows (an Alert, a retry button); announced.
footerReactNode—Under the table: a Pagination, a total.
labelsPartial<DataTableLabels>—The words, passed translated; English by default.
layout"table" | "auto" | "cards"autoauto (default): a table, cards below 36rem of container width. table or cards to force one.
loadingboolean—Rows are loading: skeleton rows (loadingRows of them) and aria-busy.
loadingRowsnumber5How many skeleton rows while loading. Default 5.
manualSortboolean—The server sorts (onSortChange fetches): the rows are shown as given.
onSelectedChange((selected: string[]) => void)—Called with the new selection.
onSortChange((sort: DataTableSort) => void)—Called when a header asks for a new sort.
rowLabel((row: T) => string)—The name of a row in its checkbox's label (default: its id).
selectableboolean—Adds a checkbox per row and one in the header.
selectedreadonly string[]—The ids selected (controlled).
showCaptionboolean—Shows the caption above the table.
sortDataTableSort—The sorted column (controlled), null for none.
virtualize{ rowHeight: number; height: number; overscan?: number; }—Renders only the rows in view (fixed rowHeight, a scrolling body of height px). Forces the table layout.

Accessibilité

  • A table with a caption (hidden unless showCaption) and scope="col" headers; the roles are written out, so the cards keep the table's semantics.
  • The sorted column carries aria-sort; a sortable header is a button that says its state with aria-pressed.
  • While loading the table is aria-busy and its caption says so; an error is announced (role="alert").
  • Windowed rows carry aria-rowindex and the table aria-rowcount: a screen reader knows where it is in the whole list; the scrolling body is a focusable region.

Clavier

TouchesAction
TabReaches the sort buttons of the headers, the checkboxes and the links of the cells.
SpaceToggles the focused checkbox, or sorts by the focused header.

Bonnes pratiques

  • Give every column a header (it labels the value in a card) and the row's name a card: "title" column.
  • Sort on the server (manualSort + onSortChange) when the table shows a page of a larger list.
  • Put a Pagination in footer and a FilterBar above; keep the filters and the page in the address.
  • Say what failed in error with a way to retry; say what to do next in empty (an EmptyState with an action).
  • Align amounts and counts to the end (align: "end") in tabular numbers.

Générée depuis le code de @krizaka/ui 2.4.0 : son meta.ts, ses exemples et ses types.Modifier cette documentation sur GitHub

Sur cette page