Design System
Patterns & Recipes

How do I build a table?

TanStack Table, via ui-kit's DataTable — the one true table.

Prescribed: TanStack Table via DataTable. Don't reach for another table library or hand-roll sort/pagination state — DataTable already wraps TanStack's headless engine with this design system's responsive layout (a real <table> on desktop, stacked cards on phone), sortable headers with correct aria-sort, and built-in loading/error states.

The approved implementation

Define your rows' shape and a plain TanStack ColumnDef[], then hand both to DataTable with an accessible caption. Sorting, responsive column hiding (via each column's meta.responsiveClassName), and the loading/error states all come for free — you don't wire any of it yourself.

  • RouteFirst Passage to the West
    Days2
    ServiceGoldLeaf
  • RouteJourney through the Clouds
    Days2
    ServiceSilverLeaf
  • RouteRainforest to Gold Rush
    Days2
    ServiceGoldLeaf

When to reach for something else

  • Rows can be selected (bulk actions, checkboxes) → SelectableDataTable builds on the same DataTable engine with a selection column already wired.
  • Just showing a handful of static key/value rows, no sorting or responsiveness needed → the plain Table primitives are lighter-weight and enough.
  • Metric/KPI rows with a trend column → MetricTable composes DataTable with a DeltaText change column already built in.

Do / Don't

  • Do pass a real, accessible caption — it's rendered as a visually-hidden <caption>, not decoration.
  • Do use isLoading/error/onRetry for anything backed by a real fetch — see the Data-fetching recipe for the server side of this.
  • Don't implement your own sort state, pagination, or a second table component for "just this one case" — extend DataTable's columns instead; that's exactly what its meta escape hatch is for.

On this page