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.
Import
import { DataTable } from '@nostromo/ui-core'
// or
import { DataTable } from '@nostromo/ui-core/data-table'Usage
import { DataTable } from '@nostromo/ui-core'
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 = [
{ 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}
/>
)
}Live Examples
Live Example
View Code
import { DataTable } from '@nostromo/ui-core'
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 = [...
Live Example
View Code
import { DataTable } from '@nostromo/ui-core'
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 = [...
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 '@nostromo/ui-core'
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