tablecnFilter. Sort. Share.
pnpm dlx shadcn@latest add @tablecn/data-table- qsearch box
- filterFilter button and chips
- sortclick a header
- pagepagination
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.
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>
)
}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.
filter-builderFilter button, panel, rule rows, chipsdata-tableTable, headers, pagination, Columns menu, toolbar@querycn/table-reactuseDataTable on TanStack Table v9@querycn/filter-nextNext.js App Router adapter@querycn/filter-reactProvider, hooks, URL adapters@querycn/filter-coreRules, URL codec, backend serializersYour 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.