nessra uinessra ui

A powerful data table component with sorting, filtering, pagination, row selection and faceted filters.

Loading...
"use client"

import { ColumnDef } from "@tanstack/react-table"

About

The DataTable component is built on top of TanStack Table and provides a powerful, flexible data table with:

  • Column sorting with dropdown (Asc/Desc/Hide)
  • Text filtering and faceted filters
  • Pagination with page numbers or simple navigation
  • Row selection with callbacks
  • Column visibility toggle
  • Loading skeleton state
  • Custom empty state
  • Row click handler
  • Controlled state for URL sync

Installation

pnpmnpmyarnbun
pnpm dlx shadcn@latest add https://nessra-ui.vercel.app/r/data-table.json

Usage

import { ColumnDef } from "@tanstack/react-table"
 
import { DataTable } from "@/components/ui/data-table"
type User = {
  id: string
  name: string
  email: string
}
 
const columns: ColumnDef<User>[] = [
  { accessorKey: "name", header: "Name" },
  { accessorKey: "email", header: "Email" },
]
 
const data: User[] = [
  { id: "1", name: "John", email: "john@example.com" },
  { id: "2", name: "Jane", email: "jane@example.com" },
]
 
return <DataTable columns={columns} data={data} />

Examples

Basic Table

Loading...
"use client"

import { ColumnDef } from "@tanstack/react-table"

Advanced with Faceted Filters

This example shows faceted filters, row selection, page numbers, and sortable column headers.

Loading...
"use client"

import * as React from "react"

Loading State

Use isLoading to show a skeleton while data is loading.

Loading...
"use client"

import * as React from "react"

Exported Components

The data-table exports multiple components you can use:

ComponentDescription
DataTableMain table component
DataTableColumnHeaderSortable column header with dropdown
DataTablePaginationPagination with page numbers
DataTableToolbarToolbar with filter, facets, view options
DataTableFacetedFilterMulti-select filter with counts
DataTableViewOptionsColumn visibility toggle

Using DataTableColumnHeader

import { DataTableColumnHeader } from "@/components/ui/data-table"
 
const columns: ColumnDef<Task>[] = [
  {
    accessorKey: "title",
    header: ({ column }) => (
      <DataTableColumnHeader column={column} title="Title" />
    ),
  },
]

Faceted Filters

import { DataTable, FacetedFilterConfig } from "@/components/ui/data-table"
 
const facetedFilters: FacetedFilterConfig[] = [
  {
    column: "status",
    title: "Status",
    options: [
      { label: "Todo", value: "todo" },
      { label: "Done", value: "done" },
    ],
  },
]
 
return (
  <DataTable columns={columns} data={data} facetedFilters={facetedFilters} />
)

Column Definitions

Columns are defined using TanStack Table's ColumnDef type:

const columns: ColumnDef<Payment>[] = [
  {
    accessorKey: "email",
    header: "Email",
  },
  {
    accessorKey: "amount",
    header: () => <div className="text-right">Amount</div>,
    cell: ({ row }) => {
      const amount = parseFloat(row.getValue("amount"))
      const formatted = new Intl.NumberFormat("en-US", {
        style: "currency",
        currency: "USD",
      }).format(amount)
      return <div className="text-right font-medium">{formatted}</div>
    },
  },
]

Row Selection Column

Add a selection column using the Checkbox component:

import { Checkbox } from "@/components/ui/checkbox"
 
// In your columns array:
{
  id: "select",
  header: ({ table }) => (
    <Checkbox
      checked={table.getIsAllPageRowsSelected()}
      onCheckedChange={(value) => table.toggleAllPageRowsSelected(!!value)}
    />
  ),
  cell: ({ row }) => (
    <Checkbox
      checked={row.getIsSelected()}
      onCheckedChange={(value) => row.toggleSelected(!!value)}
    />
  ),
  enableSorting: false,
  enableHiding: false,
}

Controlled State

For URL sync or external state management, you can control the table state from outside the component.

Basic Example

const [sorting, setSorting] = useState<SortingState>([])
const [pagination, setPagination] = useState({ pageIndex: 0, pageSize: 10 })
 
return (
  <DataTable
    columns={columns}
    data={data}
    sorting={sorting}
    onSortingChange={setSorting}
    pagination={pagination}
    onPaginationChange={setPagination}
  />
)

With nuqs (URL State)

Use nuqs to sync table state with URL query parameters:

import { SortingState } from "@tanstack/react-table"
import { parseAsInteger, parseAsJson, useQueryState } from "nuqs"
 
export function UsersTable({ data, columns }) {
  const [page, setPage] = useQueryState("page", parseAsInteger.withDefault(0))
  const [pageSize, setPageSize] = useQueryState(
    "size",
    parseAsInteger.withDefault(10)
  )
  const [sorting, setSorting] = useQueryState<SortingState>(
    "sort",
    parseAsJson<SortingState>().withDefault([])
  )
 
  return (
    <DataTable
      columns={columns}
      data={data}
      pagination={{ pageIndex: page, pageSize }}
      onPaginationChange={(state) => {
        setPage(state.pageIndex)
        setPageSize(state.pageSize)
      }}
      sorting={sorting}
      onSortingChange={setSorting}
    />
  )
}

This enables:

  • Shareable URLs: /users?page=2&size=20&sort=[{"id":"name","desc":false}]
  • Browser history: Back/forward navigation works with table state
  • Bookmarks: Users can save filtered/sorted views

API Reference

DataTable

PropTypeDefaultDescription
columnsColumnDef<TData>[]-Column definitions
dataTData[]-Table data
isLoadingbooleanfalseShow loading skeleton
emptyStateReactNode"No results."Custom empty state
filterColumnstring-Column key to filter on
filterPlaceholderstring"Filter..."Placeholder for filter input
facetedFiltersFacetedFilterConfig[][]Faceted filter configs
showPaginationbooleantrueShow pagination controls
showPageSizeSelectorbooleantrueShow rows per page selector
showPageNumbersbooleanfalseShow clickable page numbers
pageSizeOptionsnumber[][10, 20, 30, 40, 50]Available page size options
defaultPageSizenumber10Initial page size
defaultSortingSortingState[]Initial sorting state
showColumnTogglebooleanfalseShow column visibility dropdown
enableRowSelectionbooleanfalseEnable row selection
getRowId(row: TData) => string-Custom row ID function
onRowSelectionChange(selection: RowSelectionState) => void-Row selection callback
onRowClick(row: TData) => void-Row click callback
paginationPaginationState-Controlled pagination state
onPaginationChange(state: PaginationState) => void-Pagination change callback
sortingSortingState-Controlled sorting state
onSortingChange(state: SortingState) => void-Sorting change callback
columnFiltersColumnFiltersState-Controlled filter state
onColumnFiltersChange(state: ColumnFiltersState) => void-Filter change callback
toolbarChildrenReactNode-Custom toolbar content

FacetedFilterConfig

PropTypeDescription
columnstringColumn ID to filter
titlestringFilter button label
optionsFacetedFilterOption[]Available filter options

FacetedFilterOption

PropTypeDescription
labelstringDisplay label
valuestringFilter value
iconComponentType<{ className?: string }>Optional icon