Skip to content

Table

A read-only table on native table markup with a caption, row headers and optional sorting. Pick it for reports and summaries; on a phone it either scrolls in its own box or stacks each row into a labelled card.

  • Table

PreviewLink to the section Preview

Live in all three themes. Everything here is interactive.

Light theme, Table

Team members
Actions
Ada LovelaceOwner12
Alan TuringViewer1
Grace HopperEditor4
Team members, stacked on narrow screens
Actions
Ada LovelaceOwner12
Alan TuringViewer1
Grace HopperEditor4
Empty
NameRole
Nobody has joined yet.
Loading
NameRole
Loading members
Error
NameRole

Dark theme, Table

Team members
Actions
Ada LovelaceOwner12
Alan TuringViewer1
Grace HopperEditor4
Team members, stacked on narrow screens
Actions
Ada LovelaceOwner12
Alan TuringViewer1
Grace HopperEditor4
Empty
NameRole
Nobody has joined yet.
Loading
NameRole
Loading members
Error
NameRole

High contrast theme, Table

Team members
Actions
Ada LovelaceOwner12
Alan TuringViewer1
Grace HopperEditor4
Team members, stacked on narrow screens
Actions
Ada LovelaceOwner12
Alan TuringViewer1
Grace HopperEditor4
Empty
NameRole
Nobody has joined yet.
Loading
NameRole
Loading members
Error
NameRole

UsageLink to the section Usage

tsx
import { Table } from '@skribly/ui/data'
tsx
<Table
  caption="Team members"
  columns={[
    { id: 'name', header: 'Name', isRowHeader: true, allowsSorting: true, cell: (m) => m.name },
    { id: 'seats', header: 'Seats', kind: 'numeric', cell: (m) => m.seats }
  ]}
  rows={members}
  rowKey={(m) => m.id}
  layout="stack"
  sort={sort}
  onSortChange={setSort}
  emptyState="Nobody has joined yet."
/>

Every label is a prop, so the app passes its own words in its own language. See no built-in text.

AccessibilityLink to the section Accessibility

  • Native table semantics: the caption names it, sortable headers carry aria-sort and hold a real button, and row headers are read while moving down a column.
  • The stacked layout keeps explicit table roles and shows each column name next to its value.
  • A box that overflows becomes a focusable, named region so it scrolls from the keyboard.
  • Loading is a polite status with aria-busy on the table; an error is an assertive alert.

This demo runs through axe in all three themes on every test run. See what the tests check.

Search this site

Arrows move through the results, Enter opens one, Esc closes. Ctrl K /