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
Search
- 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
searchTermandonSearchTermChangefor 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
columnFiltersandonColumnFiltersChangefor server-side filtering
Sorting
- Column sorting with ascending/descending order
- Default sort column and direction
- Controlled mode - Use
sortColumn,sortDirection, andonSortChangefor 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, andtotalItems - Page size options (10, 20, 50, 100 by default)
- Results summary showing current range and total
- Can be disabled for small datasets
Props
| Prop | Type | Default | Required | Description |
|---|---|---|---|---|
data | T[] | - | Yes | Array of data objects to display |
columns | TableColumn<T>[] | - | Yes | Column definitions (see TableColumn interface) |
searchable | boolean | true | No | Enable global search functionality |
searchPlaceholder | string | "Search..." | No | Placeholder text for search input |
searchKeys | Array<keyof T | string> | undefined | No | Specific columns to search (defaults to all columns) |
onSearch | (searchTerm: string, filteredData: T[]) => void | undefined | No | Callback when search term changes |
searchTerm | string | undefined | No | Controlled search term (for server-side search) |
onSearchTermChange | (searchTerm: string) => void | undefined | No | Callback when search term changes (controlled mode) |
filterable | boolean | false | No | Enable column filtering |
filters | ColumnFilter<T>[] | [] | No | Filter definitions (see ColumnFilter interface) |
onFilter | (filters: Record<string, unknown>, filteredData: T[]) => void | undefined | No | Callback when filters change |
columnFilters | Record<string, unknown> | undefined | No | Controlled column filters (for server-side filtering) |
onColumnFiltersChange | (filters: Record<string, unknown>) => void | undefined | No | Callback when filters change (controlled mode) |
defaultSortColumn | string | undefined | No | Default column to sort by |
defaultSortDirection | "asc" | "desc" | "asc" | No | Default sort direction |
sortColumn | string | undefined | No | Controlled sort column (for server-side sorting) |
sortDirection | "asc" | "desc" | undefined | No | Controlled sort direction (for server-side sorting) |
onSortChange | (column: string, direction: "asc" | "desc") => void | undefined | No | Callback when sort changes (controlled mode) |
defaultPageSize | number | 10 | No | Default number of items per page |
currentPage | number | undefined | No | Controlled current page (for server-side pagination) |
pageSize | number | undefined | No | Controlled page size (for server-side pagination) |
onPageChange | (page: number) => void | undefined | No | Callback when page changes (controlled mode) |
onPageSizeChange | (size: number) => void | undefined | No | Callback when page size changes (controlled mode) |
totalItems | number | undefined | No | Total number of items (required for server-side pagination) |
pageSizeOptions | number[] | [10, 20, 50, 100] | No | Available page size options |
showPagination | boolean | true | No | Show pagination controls |
showSearch | boolean | true | No | Show search bar |
showFilters | boolean | true | No | Show filter controls |
rowKey | keyof T | ((record: T) => string | number) | "id" | No | Key to identify rows |
emptyText | string | "No data found" | No | Text to show when no data |
className | string | undefined | No | Additional CSS classes |
variant | "default" | "striped" | "bordered" | "hover" | "elevated" | "interactive" | "default" | No | Table visual variant |
size | "sm" | "md" | "lg" | "md" | No | Table size |
loading | boolean | false | No | Show loading state |
caption | string | undefined | No | Table caption (for accessibility) |
onRowClick | (record: T, index: number) => void | undefined | No | Callback when row is clicked |
selection | SelectionConfig<T> | undefined | No | Row 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
Basic DataTable with Search
<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
rowKeyfor 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
Related Components
- Table - Basic table component
- Input - Used for search input
- Select - Used for filter dropdowns
- Pagination - Used for pagination controls
Last updated on