Skip to content

Core Components

Essential building blocks of the data table including DataTableRoot, DataTable, and structure components.

Core components are the essential building blocks of the data table. They handle table initialization, context management, and basic structure.

The DataTableRoot component provides the table context to all child components. You should always wrap your table in a DataTableRoot. It initializes the TanStack Table instance and manages table state.

import { DataTableRoot } from "@/components/niko-table/core"
export function MyTable({ data }: { data: User[] }) {
return (
<DataTableRoot data={data} columns={columns}>
{/* child components */}
</DataTableRoot>
)
}
NameTypeDescription
dataTData[]The data array to display in the table.
columnsDataTableColumnDef<TData>[]Column definitions array.
tableTable<TData>Pre-configured TanStack Table instance (optional).
configDataTableConfigConfiguration object for feature toggles.
isLoadingbooleanLoading state for the table.
getRowId(row: TData, index: number) => stringCustom function to get row IDs.
classNamestringAdditional CSS classes.
NameTypeDescription
onGlobalFilterChange(value: GlobalFilter) => voidCalled when global filter changes.
onPaginationChange(updater: Updater<PaginationState>) => voidCalled when pagination changes.
onSortingChange(updater: Updater<SortingState>) => voidCalled when sorting changes.
onColumnFiltersChange(updater: Updater<ColumnFiltersState>) => voidCalled when column filters change.
onColumnVisibilityChange(updater: Updater<VisibilityState>) => voidCalled when column visibility changes.
onRowSelectionChange(updater: Updater<RowSelectionState>) => voidCalled when row selection changes.
onExpandedChange(updater: Updater<ExpandedState>) => voidCalled when expanded state changes.
onRowSelection(selectedRows: TData[]) => voidCalled with selected row data.

The config prop accepts a DataTableConfig object with the following properties:

NameTypeDefaultDescription
enablePaginationbooleantrueEnable pagination.
enableFiltersbooleantrueEnable filtering.
enableSortingbooleantrueEnable sorting.
enableRowSelectionbooleanfalseEnable row selection.
enableMultiSortbooleantrueEnable multi-column sorting.
enableGroupingbooleanfalseEnable column grouping.
enableExpandingbooleanfalseEnable row expansion.
manualSortingbooleanfalseEnable server-side sorting.
manualPaginationbooleanfalseEnable server-side pagination.
manualFilteringbooleanfalseEnable server-side filtering.
pageCountnumber-Total pages (required for server-side pagination).
initialPageSizenumber10Initial page size.
initialPageIndexnumber0Initial page index.
autoResetPageIndexboolean-Auto-reset page on filter/sort change. Defaults to false when manualPagination: true, otherwise true.
autoResetExpandedbooleantrueAuto-reset expanded rows on filter/sort change.

Low-level context provider used internally by DataTableRoot. Use this directly when you need to provide a pre-configured TanStack Table instance to the context (e.g., when using useReactTable yourself).

import { DataTableProvider } from "@/components/niko-table/core"
import { useReactTable, getCoreRowModel } from "@tanstack/react-table"
const table = useReactTable({ data, columns, getCoreRowModel: getCoreRowModel() })
<DataTableProvider table={table} columns={columns} isLoading={false}>
{/* child components can use useDataTable() */}
</DataTableProvider>
NameTypeDescription
tableDataTableInstance<TData>TanStack Table instance (required).
columnsDataTableColumnDef<TData>[]Column definitions (optional).
isLoadingbooleanLoading state (optional).
childrenReact.ReactNodeChild components.

The raw React context object. Useful for advanced scenarios where you need direct access to the context (e.g., conditional rendering based on context availability).

import { DataTableContext } from "@/components/niko-table/core"
import { useContext } from "react"
const context = useContext(DataTableContext)

The main table container component that wraps the table structure and provides scrolling behavior.

import { DataTable } from "@/components/niko-table/core"
<DataTable className="rounded-md border" height={600}>
<DataTableHeader />
<DataTableBody />
</DataTable>
NameTypeDefaultDescription
classNamestring-Additional CSS classes. Height utilities (e.g., h-[600px]) are automatically extracted and applied.
childrenReact.ReactNode-Child components (Header, Body).
heightnumber | string-Sets the height of the table container. Enables vertical scrolling and scroll event callbacks.
maxHeightnumber | string-Sets the maximum height of the table container. Defaults to the height value if not specified.

Renders the table header with sortable columns.

import { DataTableHeader } from "@/components/niko-table/core"
<DataTableHeader sticky={true} />
NameTypeDefaultDescription
classNamestring-Additional CSS classes.
stickybooleantrueMakes the header sticky at the top when scrolling.

Renders the table body with rows. Supports scroll events and row expansion.

import {
DataTableBody,
DataTableSkeleton,
DataTableEmptyBody,
} from "@/components/niko-table/core"
<DataTableBody
onScroll={e => console.log(`Scrolled ${e.percentage}%`)}
onScrolledBottom={() => loadMore()}
>
<DataTableSkeleton />
<DataTableEmptyBody />
</DataTableBody>
NameTypeDefaultDescription
classNamestring-Additional CSS classes.
childrenReact.ReactNode-Child components (Skeleton, EmptyBody).
onScroll(event: ScrollEvent) => void-Scroll event handler.
onScrolledTop() => void-Called when scrolled to top.
onScrolledBottom() => void-Called when scrolled to bottom.
scrollThresholdnumber50Threshold for scroll events.
onRowClick(row: TData) => void-Called when a row is clicked.

The ScrollEvent object passed to onScroll contains:

PropertyTypeDescription
scrollTopnumberCurrent scroll position from top.
scrollHeightnumberTotal scrollable height.
clientHeightnumberVisible height of the container.
isTopbooleanWhether scrolled to the top.
isBottombooleanWhether scrolled to the bottom.
percentagenumberScroll percentage (0-100).

Shows a loading skeleton when isLoading is true. Automatically matches the table structure.

<DataTableBody>
<DataTableSkeleton rows={5} />
</DataTableBody>
NameTypeDefaultDescription
rowsnumber5Number of skeleton rows to display.
colSpannumber-Number of columns (auto-detected if not provided).
classNamestring-Additional CSS classes.
cellClassNamestring-CSS classes for skeleton cells.
skeletonClassNamestring-CSS classes for skeleton elements.
childrenReact.ReactNode-Custom skeleton content (replaces rows).

Shows an empty state when there’s no data. Uses composition pattern with DataTableEmpty* components.

<DataTableBody>
<DataTableEmptyBody>
<DataTableEmptyIcon>
<PackageOpen className="size-12" />
</DataTableEmptyIcon>
<DataTableEmptyMessage>
<DataTableEmptyTitle>No products found</DataTableEmptyTitle>
<DataTableEmptyDescription>
Get started by adding your first product
</DataTableEmptyDescription>
</DataTableEmptyMessage>
<DataTableEmptyFilteredMessage>
No results match your filters
</DataTableEmptyFilteredMessage>
<DataTableEmptyActions>
<Button onClick={handleAdd}>Add Product</Button>
</DataTableEmptyActions>
</DataTableEmptyBody>
</DataTableBody>
NameTypeDefaultDescription
childrenReact.ReactNode-Empty state composition components.
colSpannumber-Number of columns (auto-detected if not provided).
classNamestring-Additional CSS classes.

Shows a loading indicator when isLoading is true.

<DataTableBody>
<DataTableLoading>
<Spinner />
</DataTableLoading>
</DataTableBody>
NameTypeDefaultDescription
childrenReact.ReactNode-Custom loading content.
colSpannumber-Number of columns (auto-detected if not provided).
classNamestring-Additional CSS classes.

Error boundary component that catches errors in the data table component tree and displays a fallback UI.

import { DataTableErrorBoundary } from "@/components/niko-table/core"
<DataTableErrorBoundary
onError={(error, errorInfo) => {
console.error("Table error:", error)
trackError(error)
}}
>
<DataTableRoot data={data} columns={columns}>
{/* table components */}
</DataTableRoot>
</DataTableErrorBoundary>
NameTypeDefaultDescription
childrenReact.ReactNode-The content to render when there’s no error.
fallbackReact.ReactNode-Custom fallback UI to show when an error occurs.
onError(error: Error, errorInfo: React.ErrorInfo) => void-Callback fired when an error is caught.
showResetButtonbooleantrueWhether to show a reset button.
resetButtonTextstring"Try Again"Custom reset button text.

For large datasets (1000+ rows), use the virtualized variants for optimal performance.

Virtualized table header component.

import {
DataTableVirtualizedHeader,
DataTableVirtualizedBody,
} from "@/components/niko-table/core"
<DataTable>
<DataTableVirtualizedHeader />
<DataTableVirtualizedBody estimateSize={34} overscan={20}>
{/* rows */}
</DataTableVirtualizedBody>
</DataTable>
NameTypeDefaultDescription
classNamestring-Additional CSS classes.
stickybooleantrueMakes the header sticky at the top when scrolling.

Virtualized table body for rendering thousands of rows efficiently.

NameTypeDefaultDescription
childrenReact.ReactNode-Child components (VirtualizedSkeleton, VirtualizedEmptyBody).
estimateSizenumber34Estimated row height in pixels.
overscannumber20Number of items to render outside visible area.
classNamestring-Additional CSS classes.
onScroll(event: ScrollEvent) => void-Scroll event handler.
onScrolledTop() => void-Called when scrolled to top.
onScrolledBottom() => void-Called when scrolled to bottom.
scrollThresholdnumber50Threshold for scroll events.
onRowClick(row: TData, event: React.MouseEvent) => void-Called when a row is clicked.

Empty state component for virtualized tables.

import {
DataTableVirtualizedBody,
DataTableVirtualizedEmptyBody,
DataTableEmptyIcon,
DataTableEmptyMessage,
DataTableEmptyTitle,
DataTableEmptyDescription,
} from "@/components/niko-table/core"
import { PackageOpen } from "lucide-react"
<DataTableVirtualizedBody estimateSize={34}>
<DataTableVirtualizedEmptyBody>
<DataTableEmptyIcon>
<PackageOpen className="size-12" />
</DataTableEmptyIcon>
<DataTableEmptyMessage>
<DataTableEmptyTitle>No data found</DataTableEmptyTitle>
<DataTableEmptyDescription>
Get started by adding your first item
</DataTableEmptyDescription>
</DataTableEmptyMessage>
</DataTableVirtualizedEmptyBody>
</DataTableVirtualizedBody>
NameTypeDefaultDescription
childrenReact.ReactNode-Empty state composition components.
colSpannumber-Number of columns (auto-detected if not provided).
classNamestring-Additional CSS classes.

Loading skeleton for virtualized tables.

import {
DataTableVirtualizedBody,
DataTableVirtualizedSkeleton,
} from "@/components/niko-table/core"
<DataTableVirtualizedBody estimateSize={34}>
<DataTableVirtualizedSkeleton rows={10} estimateSize={34} />
</DataTableVirtualizedBody>
NameTypeDefaultDescription
rowsnumber5Number of skeleton rows to display.
estimateSizenumber34Estimated row height (should match VirtualizedBody).
classNamestring-Additional CSS classes.
cellClassNamestring-CSS classes for skeleton cells.
skeletonClassNamestring-CSS classes for skeleton elements.
childrenReact.ReactNode-Custom skeleton content.

Loading indicator for virtualized tables.

import {
DataTableVirtualizedBody,
DataTableVirtualizedLoading,
} from "@/components/niko-table/core"
import { Loader2 } from "lucide-react"
<DataTableVirtualizedBody estimateSize={34}>
<DataTableVirtualizedLoading>
<div className="flex items-center justify-center p-8">
<Loader2 className="size-6 animate-spin" />
<span className="ml-2">Loading...</span>
</div>
</DataTableVirtualizedLoading>
</DataTableVirtualizedBody>
NameTypeDefaultDescription
childrenReact.ReactNode-Custom loading content.
colSpannumber-Number of columns (auto-detected if not provided).
classNamestring-Additional CSS classes.