Basic Table
Add pagination, sorting, and column visibility controls to your data table.
Products
Preview with Controlled State
Products
View Full State Object
[]
{
"pageIndex": 0,
"pageSize": 5
}{}Introduction
Section titled “Introduction”The Basic Table builds on the Simple Table by adding pagination, sorting, and column visibility. This is the most common table implementation and suitable for most use cases.
Installation
Section titled “Installation”Install the DataTable core and add-ons for this example:
First time using
@niko-table? See the Installation Guide to set up the registry.
For other add-ons or manual copy-paste, see the Installation Guide.
Prerequisites
Section titled “Prerequisites”We are going to build a table to show products. Here’s what our data looks like:
type Product = { id: string name: string category: string price: number stock: number}
const data: Product[] = [ { id: "1", name: "Laptop", category: "Electronics", price: 999, stock: 50 }, { id: "2", name: "Mouse", category: "Electronics", price: 29, stock: 150 }, // ...]Basic Table
Section titled “Basic Table”Let’s start by building a basic table with pagination and sorting.
Column Definitions
Section titled “Column Definitions”First, we’ll define our columns with sortable headers.
"use client"
import { DataTableColumnHeader, DataTableColumnTitle,} from "@/components/niko-table/components/data-table-column-header"import { DataTableColumnSortMenu } from "@/components/niko-table/components/data-table-column-sort"import type { DataTableColumnDef } from "@/components/niko-table/types"
export type Product = { id: string name: string category: string price: number stock: number}
export const columns: DataTableColumnDef<Product>[] = [ { accessorKey: "name", header: () => ( <DataTableColumnHeader> <DataTableColumnTitle /> <DataTableColumnSortMenu /> </DataTableColumnHeader> ), meta: { label: "Product" }, }, { accessorKey: "category", header: () => ( <DataTableColumnHeader> <DataTableColumnTitle /> <DataTableColumnSortMenu /> </DataTableColumnHeader> ), meta: { label: "Category" }, }, { accessorKey: "price", header: () => ( <DataTableColumnHeader> <DataTableColumnTitle /> <DataTableColumnSortMenu /> </DataTableColumnHeader> ), meta: { label: "Price" }, cell: ({ row }) => { const price = parseFloat(row.getValue("price")) return <div className="font-medium">${price.toFixed(2)}</div> }, }, { accessorKey: "stock", header: () => ( <DataTableColumnHeader> <DataTableColumnTitle /> <DataTableColumnSortMenu /> </DataTableColumnHeader> ), meta: { label: "Stock" }, },]<DataTable /> component
Section titled “<DataTable /> component”Next, we’ll create a <DataTable /> component with pagination and sorting enabled.
"use client"
import { DataTableRoot } from "@/components/niko-table/core/data-table-root"import { DataTable } from "@/components/niko-table/core/data-table"import { DataTableHeader, DataTableBody,} from "@/components/niko-table/core/data-table-structure"import { DataTableToolbarSection } from "@/components/niko-table/components/data-table-toolbar-section"import { DataTablePagination } from "@/components/niko-table/components/data-table-pagination"import { DataTableViewMenu } from "@/components/niko-table/components/data-table-view-menu"import { DataTableColumnHeader, DataTableColumnTitle,} from "@/components/niko-table/components/data-table-column-header"import { DataTableColumnSortMenu } from "@/components/niko-table/components/data-table-column-sort"import type { DataTableColumnDef } from "@/components/niko-table/types"
type Product = { id: string name: string category: string price: number stock: number}
const columns: DataTableColumnDef<Product>[] = [ { accessorKey: "name", header: () => ( <DataTableColumnHeader> <DataTableColumnTitle /> <DataTableColumnSortMenu /> </DataTableColumnHeader> ), meta: { label: "Product" }, }, { accessorKey: "category", header: () => ( <DataTableColumnHeader> <DataTableColumnTitle /> <DataTableColumnSortMenu /> </DataTableColumnHeader> ), meta: { label: "Category" }, }, { accessorKey: "price", header: () => ( <DataTableColumnHeader> <DataTableColumnTitle /> <DataTableColumnSortMenu /> </DataTableColumnHeader> ), meta: { label: "Price" }, cell: ({ row }) => { const price = parseFloat(row.getValue("price")) return <div className="font-medium">${price.toFixed(2)}</div> }, }, { accessorKey: "stock", header: () => ( <DataTableColumnHeader> <DataTableColumnTitle /> <DataTableColumnSortMenu /> </DataTableColumnHeader> ), meta: { label: "Stock" }, },]
export function BasicTable({ data }: { data: Product[] }) { return ( <DataTableRoot data={data} columns={columns} config={{ enablePagination: true, enableSorting: true, enableMultiSort: true, initialPageSize: 10, }} > <DataTableToolbarSection className="justify-between"> <h2 className="text-lg font-semibold">Products</h2> <DataTableViewMenu /> </DataTableToolbarSection>
<DataTable> <DataTableHeader /> <DataTableBody /> </DataTable>
<DataTablePagination pageSizeOptions={[5, 10, 20]} /> </DataTableRoot> )}Pagination
Section titled “Pagination”Pagination is automatically enabled when you set enablePagination: true in the config. The DataTablePagination component provides:
- Page navigation (Previous/Next)
- Page size selector
- Current page info (e.g., “1-10 of 100”)
Custom Page Sizes
Section titled “Custom Page Sizes”You can customize the available page sizes:
<DataTablePagination pageSizeOptions={[10, 25, 50, 100]} />Sorting
Section titled “Sorting”Sorting is enabled by using DataTableColumnHeader in your column definitions. Click any column header to sort by that column.
Multi-Column Sorting
Section titled “Multi-Column Sorting”Hold Shift and click multiple column headers to sort by multiple columns:
<DataTableRoot data={data} columns={columns} config={{ enableMultiSort: true, // Enable multi-column sorting }}> {/* ... */}</DataTableRoot>Disable Sorting
Section titled “Disable Sorting”To disable sorting for a specific column:
{ accessorKey: "id", header: "ID", enableSorting: false, // This column cannot be sorted}Column Visibility
Section titled “Column Visibility”The DataTableViewMenu component adds a dropdown to show/hide columns:
<DataTableToolbarSection className="justify-between"> <h2 className="text-lg font-semibold">Products</h2> <DataTableViewMenu /></DataTableToolbarSection>Disable Column Hiding
Section titled “Disable Column Hiding”To prevent specific columns from being hidden:
{ accessorKey: "id", header: "ID", enableHiding: false, // This column cannot be hidden}Controlled State
Section titled “Controlled State”Full control over table state:
import { useState } from "react"import type { PaginationState, SortingState, VisibilityState,} from "@tanstack/react-table"
export function ControlledBasicTable({ data }: { data: Product[] }) { const [pagination, setPagination] = useState<PaginationState>({ pageIndex: 0, pageSize: 10, }) const [sorting, setSorting] = useState<SortingState>([]) const [columnVisibility, setColumnVisibility] = useState<VisibilityState>({})
return ( <DataTableRoot data={data} columns={columns} state={{ pagination, sorting, columnVisibility, }} onPaginationChange={setPagination} onSortingChange={setSorting} onColumnVisibilityChange={setColumnVisibility} > <DataTableToolbarSection className="justify-between"> <h2 className="text-lg font-semibold">Products</h2> <DataTableViewMenu /> </DataTableToolbarSection>
<DataTable> <DataTableHeader /> <DataTableBody /> </DataTable>
<DataTablePagination /> </DataTableRoot> )}When to Use
Section titled “When to Use”✅ Use Basic Table when:
- You have 50+ rows that need pagination
- Users need to sort data
- You want column visibility controls
- You don’t need search or filtering
❌ Consider other options when:
- Dataset is < 50 rows (use Simple Table)
- Users need to search (use Search Table)
- You need advanced filters (use Advanced Table)
Next Steps
Section titled “Next Steps”- Search Table - Add global search
- Advanced Table - Add advanced filtering