Search documentation

Search for a page or heading...

tablecn
0
NewThe data table block is here

tablecnFilter. Sort. Share.

A data table for shadcn/ui, with filters, sorting and pages synced to the URL.

pnpm dlx shadcn@latest add @tablecn/data-table
  • qsearch box
  • filterFilter button and chips
  • sortclick a header
  • pagepagination
Features

Everything a list page needs, wired together

Tested, typed and accessible, so the next admin screen takes an afternoon instead of a sprint.

A filter builder people understand

Where Status is Paid and Amount is between 10 and 50. Eight field types, fifteen operators, AND / OR, and options loaded as you type.

The URL is the state

Share a link, press back, reload: the same rows come back. A new filter goes to page 1 in the same navigation.

A layout users keep

Drag, pin, resize, hide and color columns. Saved in the browser and merged with the columns you ship later.

Client or server data

Filter and sort in the browser, or send the URL to JSON:API, django-filter, PostgREST or your own backend.

Thousands of rows

Virtualization renders only the rows in view, with the sticky header and pinned columns intact.

Three primitive libraries

Every block comes in Radix UI, Base UI and React Aria versions with the same props. Pick the one your project uses.

Keyboard and screen readers

Sort, move and resize columns from the keyboard, with every step announced. English and Vietnamese included.

Developer experience

One hook, a few components

useDataTable returns a TanStack table with the URL, the filter and the layout wired in. The components only need that table.

  • Filter, sort and page share one URL, through one adapter.
  • A new filter goes back to page 1 in the same navigation.
  • The column layout is saved under storageKey.
  • Every piece is a file in your project: restyle or rewrite it.
"use client"

export function Orders({ orders }: { orders: Order[] }) {
  const table = useDataTable({
    data: orders,
    columns,
    getRowId: (order) => order.id,
    storageKey: "orders",
  })

  return (
    <NextFilterProvider fields={fields} onApply={() => resetPagePatch()}>
      <DataTableToolbar table={table}>
        <FilterBuilder />
        <FilterChips />
      </DataTableToolbar>
      <DataTable table={table} className="h-[600px]" />
      <DataTablePagination table={table} />
    </NextFilterProvider>
  )
}
Architecture

Logic on npm, UI you own

Update the logic like any dependency. Edit the components like your own code. Take only the layers you need: the filter works without the table, and its core works without React.

Your codecopied by the shadcn CLI
filter-builderFilter button, panel, rule rows, chips
data-tableTable, headers, pagination, Columns menu, toolbar
Reactnpm, headless
@querycn/table-reactuseDataTable on TanStack Table v9
@querycn/filter-nextNext.js App Router adapter
@querycn/filter-reactProvider, hooks, URL adapters
Anywherenpm, no dependencies
@querycn/filter-coreRules, URL codec, backend serializers

Your next list page, in an afternoon

Add the blocks, declare your fields and columns, and ship a table that users can filter, share and arrange.