Skip to Content
ComponentsDataTable

DataTable

The DataTable component is an advanced table with built-in search, filtering, sorting, and pagination. It’s built on top of the Table component and provides enhanced data management capabilities.

Live Examples

Live Example
☀️
Copy
View Code
import { DataTable, type TableColumn } from '@jarllyng/nostromo' const data = [ { id: 1, name: 'John Doe', email: 'john@example.com', age: 28, department: 'Engineering', status: 'Active' }, { id: 2, name: 'Jane Smith', email: 'jane@example.com', age: 32, department: 'Marketing', status: 'Active' }, { id: 3, name: 'Bob Johnson', email: 'bob@example.com', age: 45, department: 'Sales', status: 'Inactive' }, { id: 4, name: 'Alice Brown', email: 'alice@example.com', age: 29, department: 'Engineering', status: 'Active' } ] const columns: TableColumn<(typeof data)[number]>[] = [...
Live Example
☀️
Copy
View Code
import { DataTable, type TableColumn } from '@jarllyng/nostromo' const data = [ { id: 1, name: 'John Doe', email: 'john@example.com', department: 'Engineering', status: 'Active' }, { id: 2, name: 'Jane Smith', email: 'jane@example.com', department: 'Marketing', status: 'Active' }, { id: 3, name: 'Bob Johnson', email: 'bob@example.com', department: 'Sales', status: 'Inactive' }, { id: 4, name: 'Alice Brown', email: 'alice@example.com', department: 'Engineering', status: 'Active' } ] const columns: TableColumn<(typeof data)[number]>[] = [...

Import

import { DataTable } from "@jarllyng/nostromo"; // or import { DataTable } from "@jarllyng/nostromo/data-table";

Usage

import { DataTable } from "@jarllyng/nostromo"; const data = [ { id: 1, name: "John Doe", email: "john@example.com", department: "Engineering", }, { id: 2, name: "Jane Smith", email: "jane@example.com", department: "Marketing", }, ]; const columns: TableColumn<(typeof data)[number]>[] = [ { key: "name", title: "Name", dataIndex: "name", sortable: true }, { key: "email", title: "Email", dataIndex: "email" }, { key: "department", title: "Department", dataIndex: "department", sortable: true, }, ]; export default function Example() { return ( <DataTable data={data} columns={columns} searchable={true} showPagination={true} /> ); }

Features

  • Global search across multiple columns
  • Custom search keys to specify which columns to search
  • Real-time filtering as you type
  • Search callback for custom handling
  • Controlled mode - Use searchTerm and onSearchTermChange for server-side search

Filtering

  • Column filters with multiple filter types (text, select, number, date, boolean)
  • Multiple filters can be applied simultaneously
  • Custom filter functions for advanced filtering logic
  • Clear filters button to reset all filters
  • Controlled mode - Use columnFilters and onColumnFiltersChange for server-side filtering

Sorting

  • Column sorting with ascending/descending order
  • Default sort column and direction
  • Controlled mode - Use sortColumn, sortDirection, and onSortChange for server-side sorting
  • Sort indicators in column headers

Pagination

  • Client-side pagination - Automatic pagination of data (default)
  • Server-side pagination - Controlled mode with currentPage, pageSize, onPageChange, onPageSizeChange, and totalItems
  • Page size options (10, 20, 50, 100 by default)
  • Results summary showing current range and total
  • Can be disabled for small datasets

Props

PropTypeDefaultRequiredDescription
dataT[]-YesArray of data objects to display
columnsTableColumn<T>[]-YesColumn definitions (see TableColumn interface)
searchablebooleantrueNoEnable global search functionality
searchPlaceholderstring"Search..."NoPlaceholder text for search input
searchKeysArray<keyof T | string>undefinedNoSpecific columns to search (defaults to all columns)
onSearch(searchTerm: string, filteredData: T[]) => voidundefinedNoCallback when search term changes
searchTermstringundefinedNoControlled search term (for server-side search)
onSearchTermChange(searchTerm: string) => voidundefinedNoCallback when search term changes (controlled mode)
filterablebooleanfalseNoEnable column filtering
filtersColumnFilter<T>[][]NoFilter definitions (see ColumnFilter interface)
onFilter(filters: Record<string, unknown>, filteredData: T[]) => voidundefinedNoCallback when filters change
columnFiltersRecord<string, unknown>undefinedNoControlled column filters (for server-side filtering)
onColumnFiltersChange(filters: Record<string, unknown>) => voidundefinedNoCallback when filters change (controlled mode)
defaultSortColumnstringundefinedNoDefault column to sort by
defaultSortDirection"asc" | "desc""asc"NoDefault sort direction
sortColumnstringundefinedNoControlled sort column (for server-side sorting)
sortDirection"asc" | "desc"undefinedNoControlled sort direction (for server-side sorting)
onSortChange(column: string, direction: "asc" | "desc") => voidundefinedNoCallback when sort changes (controlled mode)
defaultPageSizenumber10NoDefault number of items per page
currentPagenumberundefinedNoControlled current page (for server-side pagination)
pageSizenumberundefinedNoControlled page size (for server-side pagination)
onPageChange(page: number) => voidundefinedNoCallback when page changes (controlled mode)
onPageSizeChange(size: number) => voidundefinedNoCallback when page size changes (controlled mode)
totalItemsnumberundefinedNoTotal number of items (required for server-side pagination)
pageSizeOptionsnumber[][10, 20, 50, 100]NoAvailable page size options
showPaginationbooleantrueNoShow pagination controls
showSearchbooleantrueNoShow search bar
showFiltersbooleantrueNoShow filter controls
rowKeykeyof T | ((record: T) => string | number)"id"NoKey to identify rows
emptyTextstring"No data found"NoText to show when no data
classNamestringundefinedNoAdditional CSS classes
variant"default" | "striped" | "bordered" | "hover" | "elevated" | "interactive""default"NoTable visual variant
size"sm" | "md" | "lg""md"NoTable size
loadingbooleanfalseNoShow loading state
captionstringundefinedNoTable caption (for accessibility)
onRowClick(record: T, index: number) => voidundefinedNoCallback when row is clicked
selectionSelectionConfig<T>undefinedNoRow selection configuration (see Table component)

ColumnFilter Interface

interface ColumnFilter<T = Record<string, unknown>> { key: string; // Column key to filter type: "text" | "select" | "number" | "date" | "boolean"; options?: Array<{ // For 'select' type label: string; value: string | number; }>; placeholder?: string; // Placeholder for filter input filterFn?: (value: unknown, record: T) => boolean; // Custom filter function }

Examples

<DataTable data={employees} columns={columns} searchable={true} searchPlaceholder="Search employees..." />

DataTable with Filters

<DataTable data={employees} columns={columns} searchable={true} filterable={true} filters={[ { key: "department", type: "select", options: [ { label: "Engineering", value: "Engineering" }, { label: "Marketing", value: "Marketing" }, ], }, { key: "status", type: "select", options: [ { label: "Active", value: "Active" }, { label: "Inactive", value: "Inactive" }, ], }, ]} />

DataTable with Custom Search Keys

<DataTable data={employees} columns={columns} searchable={true} searchKeys={["name", "email"]} // Only search in name and email columns searchPlaceholder="Search by name or email..." />

DataTable with Default Sort

<DataTable data={employees} columns={columns} defaultSortColumn="name" defaultSortDirection="asc" />

DataTable without Pagination

<DataTable data={employees} columns={columns} searchable={true} showPagination={false} // Show all results />

DataTable with Server-Side Pagination (Controlled Mode)

import { useState } from "react"; import { DataTable } from "@jarllyng/nostromo"; export default function ServerSideDataTable() { const [currentPage, setCurrentPage] = useState(1); const [pageSize, setPageSize] = useState(10); const [sortColumn, setSortColumn] = useState("name"); const [sortDirection, setSortDirection] = useState<"asc" | "desc">("asc"); const [searchTerm, setSearchTerm] = useState(""); const [totalItems, setTotalItems] = useState(0); // Fetch data from server based on current state const fetchData = async () => { const response = await fetch( `/api/employees?page=${currentPage}&pageSize=${pageSize}&sort=${sortColumn}&direction=${sortDirection}&search=${searchTerm}`, ); const { data, total } = await response.json(); setTotalItems(total); return data; }; return ( <DataTable data={data} columns={columns} // Controlled props for server-side operations currentPage={currentPage} pageSize={pageSize} totalItems={totalItems} onPageChange={setCurrentPage} onPageSizeChange={setPageSize} sortColumn={sortColumn} sortDirection={sortDirection} onSortChange={(col, dir) => { setSortColumn(col); setSortDirection(dir); }} searchTerm={searchTerm} onSearchTermChange={setSearchTerm} /> ); }

Accessibility

  • WCAG 2.1 AA compliant
  • Keyboard navigation for all interactive elements
  • ARIA labels for search and filter inputs
  • Screen reader support with proper table structure
  • Focus management for pagination controls

Do’s and Don’ts

✅ Do

  • Use DataTable for large datasets that need search/filter
  • Provide meaningful column titles
  • Use appropriate filter types for each column
  • Set reasonable default page sizes
  • Include rowKey for proper row identification

❌ Don’t

  • Use DataTable for simple static tables (use Table instead)
  • Overload with too many filters
  • Use very large page sizes (>100)
  • Forget to handle empty states
  • Use without pagination for large datasets
  • Table - Basic table component
  • Input - Used for search input
  • Select - Used for filter dropdowns
  • Pagination - Used for pagination controls
Last updated on