Reference index

Components

Data table

Table with sortable headers (aria-sort, ink glyphs), a column filter, a columns popover and paging, on TanStack Table and the Eloquent table.

Preview

Stories filed this week.
Budget passes second readingPolitics1,240
Port strike enters third dayBusiness980
Museum reopens its east wingCulture760
Telescope finds a quiet starScience1,105
Council rejects the tram planPolitics870
Page 1 of 2

Install

bash

npx shadcn add @eloquent/data-table

This adds @tanstack/react-table (v9; Base UI has no data table) and the table, button, input, popover and checkbox items.

Usage

tsx

import { createDataTableColumnHelper, DataTable } from "@/components/ui/data-table";

type Story = { title: string; desk: string; words: number };
const helper = createDataTableColumnHelper<Story>();

// Keep columns and data stable: module scope or useMemo. `helper.columns([...])` types mixed value columns.
const columns = helper.columns([
  helper.accessor("title", { id: "title", header: "Story" }),
  helper.accessor("desk", { id: "desk", header: "Desk" }),
  helper.accessor("words", { id: "words", header: "Words" }),
]);

<DataTable
  columns={columns}
  data={stories}
  caption="Stories filed this week."
  labels={{
    filter: "Filter stories",
    columns: "Columns",
    previous: "Previous",
    next: "Next",
    page: (page, count) => `Page ${page} of ${count}`,
    empty: "No stories match.",
    sorted: (column, direction) => `Sorted by ${column}, ${direction === "asc" ? "ascending" : "descending"}`,
  }}
  pageSize={5}
  numericColumns={["words"]}
  filterColumn="title"
/>

Use a string header: it names the sort button and the checkbox in the columns popup. The component carries no English text; every string is a prop. Pass locale so text sorts by the language (Vietnamese diacritics included).

States

Empty result.
Words
No stories match.
Empty: one ruled row with a message.
A column that cannot be sorted.
Words
Budget passes second reading1240
Port strike enters third day980
Museum reopens its east wing760
Sortable headers are buttons with ▲▼ glyphs; a plain header has none.
StateTreatment
Sortable headerKicker button with ▲▼ stacked in grey
SortedOne ink glyph (▲ ascending, ▼ descending) and aria-sort on the header
Sort buttonInk fill on press; 2px ink outline on focus; no hover
EmptyOne ruled row with a message
Pager at an endThe disabled button: grey text and rule, not allowed

Keyboard

KeyAction
TabMoves through the filter, the columns button, the table's scroll region (with scrollLabel), the sort buttons and the pager
Enter / Space on a headerSorts ascending, then descending, then clears; the change is announced
Enter / Space on the columns buttonOpens the columns popup
Space on a column checkboxShows or hides the column
EscCloses the popup and returns focus to the columns button
Enter / Space on Previous or NextChanges the page

Vietnamese

Các bài nộp trong tuần.
Ngân sách qua vòng đọc thứ haiChính trị1.240
Đình công cảng kéo sang ngày thứ baKinh doanh980
Bảo tàng mở lại cánh phía đôngVăn hoá760
Kính thiên văn tìm thấy một ngôi sao lặngKhoa học1.105
Hội đồng bác kế hoạch xe điệnChính trị870
Trang 1 / 2

Ink adaptation

Upstream's recipe uses a dropdown menu to hide columns and ghost sort buttons with chevrons. Here the column toggle is a popover with checkboxes, paging is two plain buttons, and sort state is an ink ▲ or ▼ with aria-sort, so it never rests on colour. Row hover fills are removed.