@algodomain/smart-datatable
v0.1.13
Published
This guide explains how to use the DataTable component: core concepts, feature set, and real-world examples for client, server, and auto (hybrid) modes. It also covers filtering, sorting, pagination, selection, column management with comprehensive reset f
Readme
@algodomain/smart-datatable
This guide explains how to use the DataTable component: core concepts, feature set, and real-world examples for client, server, and auto (hybrid) modes. It also covers filtering, sorting, pagination, selection, column management with comprehensive reset functionality, localStorage persistence, and backend integration via ORM adapters.
Table of Contents
🆕 What's New
- Grid View (Card Layout) - Display rows as responsive cards, ideal for mobile
Documentation
- Package Details
- Install and Configure
- Basics
- Defining Columns
- Modes: Client, Server, Auto
- Filtering
- Sorting
- Pagination
- Selection
- Row Counts
- Grid View (Card Layout) 🆕
- Column Management
- Persistence & localStorage
- Fixed Headers and Table Height
- Styling
- Backend Integration with ORM Adapters
- Error Handling
- Performance Tips
Reference
- Complete Properties Reference
- ColumnDef Properties Reference
- Quick Reference & Common Patterns
- Dynamic Runtime Controls
- Quick Start Page
- Upcoming
Package Details
- Name:
@algodomain/smart-datatable - Support:
[email protected] - Website: algodomain.com
Install and Configure
Requirements:
- React 18+
- Tailwind CSS 4.x+
- Install the package (choose your manager):
pnpm add @algodomain/smart-datatable
# or
npm i @algodomain/smart-datatable
# or
yarn add @algodomain/smart-datatable- Make sure your Tailwind CSS entry file (e.g.,
src/index.css) sources the DataTable package so Tailwind scans its class names. Add ONE of the following@sourcelines that exists in yournode_modules:
/* Ensure Tailwind scans DataTable package classes */
@source "../node_modules/@algodomain/smart-datatable/dist/index.js";
/* OR */
@source "../node_modules/@algodomain/smart-datatable/dist/index.cjs";If your index.css uses Tailwind v4 style imports, you might already have:
@import "tailwindcss";- Import the DataTable styles once in your app (e.g., in
src/main.tsxor on the page where you use the table):
import "@algodomain/smart-datatable/style.css";- Use the component:
import { DataTable } from "@algodomain/smart-datatable";
import type { ColumnDef, APIConfig } from "@algodomain/smart-datatable";Basics
- The DataTable is a React + TypeScript component styled with Tailwind and shadcn/ui.
- Core component import:
import { DataTable } from "@algodomain/smart-datatable"
import type { ColumnDef } from "@algodomain/smart-datatable"Defining Columns
Each column describes how a field is rendered, sorted, and filtered.
interface Task {
id: string
title: string
status: "In-Progress" | "Canceled" | "Completed" | "Pending" | "New"
priority: "High" | "Medium" | "Low"
estimatedHours: number
createdAt: Date | string
assignee: string
}
const columns: ColumnDef<Task>[] = [
{ id: "id", header: "Task ID", accessorKey: "id", width: 100, sortable: true, filterable: true, dataType: "string", filterType: "text" },
{ id: "title", header: "Title", accessorKey: "title", width: 200, sortable: true, filterable: true, dataType: "string", textWrap: true },
{
id: "status",
header: "Status",
accessorKey: "status",
width: 120,
sortable: true,
filterable: true,
dataType: "string",
filterType: "select",
filterOptions: [
{ label: "New", value: "New" },
{ label: "In-Progress", value: "In-Progress" },
{ label: "Pending", value: "Pending" },
{ label: "Completed", value: "Completed" },
{ label: "Canceled", value: "Canceled" },
],
},
{ id: "estimatedHours", header: "Est. Hours", accessorKey: "estimatedHours", width: 100, sortable: true, filterable: true, dataType: "number", filterType: "number" },
{ id: "createdAt", header: "Created At", accessorKey: "createdAt", width: 180, sortable: true, filterable: true, dataType: "date", filterType: "date" },
]Notes:
dataTypeimproves filtering and sorting behavior.filterType: "select"requiresfilterOptions.textWrapcontrols whether cell text wraps within column width.
Modes: Client, Server, Auto
- Client (in-memory): Use when you already have data on the client, or want to fetch all data once from an API endpoint and handle filtering/sorting/pagination client-side.
- Server: Data is fetched via an API endpoint; sorting/filtering/pagination are handled server-side.
- Auto (hybrid): Smart caching; starts server-side and can switch to client when all records are cached.
Client Mode Examples
Client Mode with Data Prop:
<DataTable
columns={columns}
data={myTasks} // array of Task
mode="client"
// Table identification & persistence
tableId="tasks-table"
enablePersistence={true}
persistFilters={true}
persistSorting={true}
persistColumnSettings={true}
// UX
enableSelection
selectionMode="multiple"
enableFiltering
enableGlobalSearch
enableSorting
enableMultiSort
enableColumnVisibility
enableColumnReorder
enableColumnResize
enableColumnFreeze
pageSizeOptions={[5, 10, 20, 50]}
initialPageSize={10}
showColumnBorders
onRowClick={(row) => console.log("Row:", row)}
onSelectionChange={(rows) => console.log("Selected:", rows)}
/>Client Mode with API Endpoint:
<DataTable
columns={columns}
api={{ endpoint: "http://localhost:7070/task-details" }}
mode="client"
// Table identification & persistence
tableId="api-tasks-table"
enablePersistence={true}
persistFilters={true}
persistSorting={true}
persistColumnSettings={true}
// UX
enableSelection
selectionMode="multiple"
enableFiltering
enableGlobalSearch
enableSorting
enableMultiSort
enableColumnVisibility
enableColumnReorder
enableColumnResize
enableColumnFreeze
pageSizeOptions={[5, 10, 20, 50]}
initialPageSize={10}
showColumnBorders
onRowClick={(row) => console.log("Row:", row)}
onSelectionChange={(rows) => console.log("Selected:", rows)}
onError={(error) => console.error("API Error:", error)}
/>Client Mode Validation:
- ✅ Use
dataprop: All data provided directly - ✅ Use
apiprop: Fetches all data once, then handles everything client-side - ❌ Error: Cannot use both
dataandapiin client mode - the table will display a validation error
API Response Format for Client Mode: The API endpoint should return either:
- An array of objects directly:
[{...}, {...}] - An object with a
dataproperty:{ data: [{...}, {...}] }
HTTP Method Requirements:
- Client Mode: Requires GET endpoint (fetches all data once)
- Server Mode: Requires POST endpoint (sends pagination/filtering requests)
- Auto Mode: Requires POST endpoint (sends pagination/filtering requests)
API Configuration Options:
interface APIConfig {
endpoint: string; // Required API endpoint
accessTokenKey?: string; // localStorage key for access token (default: 'accessToken')
headers?: Record<string, string>; // Additional custom headers to include in requests
}API Configuration Examples:
// Simple API endpoint
<DataTable
columns={columns}
api={{ endpoint: "/api/data" }}
mode="client"
/>
// API with authentication
<DataTable
columns={columns}
api={{
endpoint: "/api/data",
accessTokenKey: "myToken",
headers: { "X-API-Key": "key123" }
}}
mode="server"
/>
// API with custom headers only
<DataTable
columns={columns}
api={{
endpoint: "/api/data",
headers: { "X-API-Key": "key123", "X-Client-ID": "client-456" }
}}
mode="auto"
/>Benefits of Client Mode with API Endpoint:
- 🚀 Single API Call: Fetches all data once, then handles filtering/sorting/pagination client-side
- ⚡ Fast Interactions: No network delays for filtering, sorting, or pagination after initial load
- 💾 Offline Capable: Works offline after initial data fetch
- 🔄 Consistent UX: Same user experience as traditional client-side tables
- 📊 Perfect for Medium Datasets: Ideal when you have 100-10,000 records that can fit in memory
Server Mode Example
<DataTable
columns={columns}
api={{ endpoint: "http://localhost:7070/task-details" }}
mode="server"
backendORM="prisma" // prisma | mongoose | typeorm | custom
// Table identification & persistence
tableId="server-tasks-table"
enablePersistence={true}
persistFilters={true}
persistSorting={true}
persistColumnSettings={true}
pageSizeOptions={[5, 10, 25, 50]}
initialPageSize={10}
enableFiltering
enableGlobalSearch
enableSorting
enableMultiSort
enableColumnVisibility
enableColumnReorder
enableColumnResize
enableColumnFreeze
maxHeight="70vh"
showColumnBorders
onError={(e) => console.error(e)}
/>Expected request payload shape (client → server):
{
"page": 1,
"pageSize": 25,
"sort": [
{ "column": "createdAt", "direction": "desc" },
{ "column": "priority", "direction": "asc" }
],
"filters": [
{ "column": "status", "operator": "=", "value": "In-Progress" },
{ "column": "estimatedHours", "operator": ">=", "value": 10 }
],
"logicalOperator": "AND"
}Expected server response:
{
"data": [ /* array of rows */ ],
"totalRecords": 1250,
"page": 1,
"pageSize": 25,
"totalPages": 50
}Auto (Hybrid) Mode Example
<DataTable
columns={columns}
api={{ endpoint: "http://localhost:7070/task-details" }}
mode="auto"
// Table identification & persistence
tableId="auto-tasks-table"
enablePersistence={true}
persistFilters={true}
persistSorting={true}
persistColumnSettings={true}
serverPageSize={10}
pageSizeOptions={[5, 10, 25, 50]}
initialPageSize={5}
enableSelection
selectionMode="multiple"
enableFiltering
enableGlobalSearch
enableSorting
enableMultiSort
enableColumnVisibility
enableColumnReorder
enableColumnResize
enableColumnFreeze
maxHeight="70vh"
showColumnBorders
/>Hybrid behavior highlights:
- Caches fetched server pages; won’t re-fetch pages already cached.
- If all records become cached, operations switch to client mode automatically.
Filtering
There are two per-column filtering UIs, selected automatically:
- Select filter (when a column has
filterType: "select"withfilterOptions). - Advanced filter for text/number/date with multiple conditions and logical operators.
Operators by type:
- String:
=,!=,contains,startsWith,endsWith,isEmpty,isNotEmpty - Number/Date: all string operators plus
>,<,>=,<=,between
Examples:
// Text contains
onFilter({ column: "title", operator: "contains", value: "auth" })
// Number between
onFilter({ column: "estimatedHours", operator: "between", value: [10, 20] })
// Select with multiple values
onFilter({ column: "status", operator: "=", value: ["In-Progress", "Pending"] })Global Search searches across all visible values.
Clear buttons:
- “Clear Filters” removes all column filters but preserves sorts.
- “Clear All” removes both filters and sorts.
Sorting
- Click a column header menu to toggle sort: asc → desc → none.
- Multi-sort is supported. The header shows sort order and direction numbers when multiple columns are active.
enableSorting
enableMultiSortPagination
- Built-in controls: rows per page, current page, first/prev/next/last.
- Text summary reflects total vs filtered counts.
Props:
pageSizeOptions(e.g.,[10, 20, 50, 100, 500])initialPageSize
Selection
- Enable with
enableSelection. selectionMode:singleormultiple.- Header checkbox selects/deselects all rows on the current page in multiple mode.
enableSelection
selectionMode="multiple"
onSelectionChange={(rows) => console.log(rows)}Row Counts
- Enable with
enableRowCounts. - Adds a lightweight numbering column so users can reference row positions easily.
- When combined with row selection, the numbering column appears immediately after the selection column.
- Works in every mode (client/server/auto) and respects pagination so numbering stays continuous across pages.
<DataTable
columns={columns}
data={myTasks}
enableRowCounts
enableSelection
/>Grid View (Card Layout)
The Grid View feature allows you to display table rows as responsive cards, ideal for mobile devices and compact displays. Users can toggle between traditional table view and grid/card view.
Enabling Grid View
To enable grid view, provide both enableGridView={true} and a renderGridItem function:
<DataTable
columns={columns}
data={myTasks}
tableId="tasks-grid-table"
enableGridView={true}
renderGridItem={(row) => (
<div className="p-4 border rounded-lg bg-card hover:shadow-md transition-shadow">
<div className="flex items-start justify-between mb-2">
<span className="font-mono text-sm text-muted-foreground">{row.id}</span>
<Badge>{row.status}</Badge>
</div>
<h3 className="font-semibold text-sm mb-2">{row.title}</h3>
<div className="flex items-center gap-2">
<span className="text-sm text-muted-foreground">{row.assignee}</span>
</div>
</div>
)}
enableSelection
selectionMode="multiple"
onSelectionChange={(rows) => console.log("Selected:", rows)}
/>Grid View Features
- Toggle Button: A Grid/Table toggle button appears in the toolbar when grid view is enabled
- Responsive Layout: Cards automatically adjust to screen size using CSS Grid with
auto-fit - Selection Support: Checkbox appears on each card when
enableSelection={true}- perfect for compare features - Row Click: Clicking a card triggers
onRowClickcallback - Consistent Heights: Cards in the same row maintain equal heights
- Mobile Default: On mobile devices (< 768px), grid view is automatically selected by default
- Persistence: View mode preference is saved to localStorage per table (requires
tableId)
Grid View Props
| Property | Type | Required | Default | Description |
|----------|------|----------|---------|-------------|
| enableGridView | boolean | ❌ Optional | false | Enables the grid/table toggle button |
| renderGridItem | (row: T) => React.ReactNode | ⚠️ Conditional | - | Custom card renderer function. Required when enableGridView={true} |
renderGridItem Function
The renderGridItem function receives a single row and returns a React element representing the card:
renderGridItem={(row) => (
// Your custom card design
<div className="p-4 border rounded-lg">
<h3>{row.title}</h3>
<p>{row.description}</p>
</div>
)}Note: Selection styling (ring highlight) is automatically applied by the DataTable when a card is selected. You don't need to handle selection styles in your renderGridItem function.
Grid View Behavior
Toolbar Changes in Grid View:
- ✅ Global search remains visible
- ✅ Clear Filters / Clear All buttons remain visible
- ✅ Grid/Table toggle button visible
- ❌ Columns dropdown (visibility/reorder) is hidden
Selection in Grid View:
- Checkbox appears in the top-right corner of each card
- Supports both
single(radio) andmultiple(checkbox) selection modes - Selected cards show a primary ring highlight
Mobile Behavior:
- Automatically defaults to grid view on screens < 768px
- View preference is persisted per table in localStorage
- Users can still toggle to table view if needed
Complete Grid View Example
import { DataTable, type ColumnDef } from "@algodomain/smart-datatable"
import { Badge } from "@/components/ui/badge"
interface Task {
id: string
title: string
status: string
priority: string
assignee: string
estimatedHours: number
}
const columns: ColumnDef<Task>[] = [
{ id: "id", header: "ID", accessorKey: "id" },
{ id: "title", header: "Title", accessorKey: "title" },
{ id: "status", header: "Status", accessorKey: "status" },
{ id: "priority", header: "Priority", accessorKey: "priority" },
{ id: "assignee", header: "Assignee", accessorKey: "assignee" },
{ id: "estimatedHours", header: "Est. Hours", accessorKey: "estimatedHours" },
]
export function TasksPage() {
return (
<DataTable
columns={columns}
data={tasks}
tableId="tasks-grid-table"
// Grid View Configuration
enableGridView={true}
renderGridItem={(row) => (
<div className="p-4 border rounded-lg bg-card hover:shadow-md transition-shadow">
{/* Header */}
<div className="flex items-start justify-between mb-2">
<span className="font-mono text-sm text-muted-foreground">{row.id}</span>
<Badge
className={
row.status === "Completed" ? "bg-green-100 text-green-800" :
row.status === "In-Progress" ? "bg-blue-100 text-blue-800" :
"bg-yellow-100 text-yellow-800"
}
>
{row.status}
</Badge>
</div>
{/* Title */}
<h3 className="font-semibold text-sm mb-2 line-clamp-2">{row.title}</h3>
{/* Assignee */}
<div className="flex items-center gap-2 mb-2">
<div className="w-6 h-6 rounded-full bg-gray-300 flex items-center justify-center text-xs">
{row.assignee.split(" ").map(n => n[0]).join("")}
</div>
<span className="text-sm text-muted-foreground">{row.assignee}</span>
</div>
{/* Footer */}
<div className="flex items-center justify-between text-sm">
<span className={
row.priority === "High" ? "text-red-600 font-medium" :
row.priority === "Medium" ? "text-yellow-600 font-medium" :
"text-green-600 font-medium"
}>
{row.priority}
</span>
<span className="text-muted-foreground">{row.estimatedHours}h</span>
</div>
</div>
)}
// Other features work in both views
enableSelection
selectionMode="multiple"
enableFiltering
enableGlobalSearch
enableSorting
pageSizeOptions={[6, 12, 24]}
initialPageSize={6}
onRowClick={(row) => console.log("Clicked:", row)}
onSelectionChange={(rows) => console.log("Selected:", rows)}
/>
)
}Column Management
- Visibility toggle in Columns menu.
- Reorder with up/down controls in Columns menu. State persists via
localStorage. - Resize by dragging the column border (enable with
enableColumnResize). - Freeze/unfreeze individual columns (left-side sticky marker) with
enableColumnFreeze. - Text wrapping toggle per column from the header menu. Persisted via
localStorage. - 🔄 Reset All Settings - Comprehensive reset button in Column Settings dropdown that:
- Resets column order to original sequence
- Shows all hidden columns
- Resets column widths to defaults
- Unfreezes all columns
- Resets text wrapping to column defaults
- Clears localStorage for fresh start
Props:
enableColumnVisibility
enableColumnReorder
enableColumnResize
enableColumnFreezeColumn width controls in ColumnDef:
width?: number
minWidth?: number // default 80
maxWidth?: number // default 500
resizable?: boolean // default true; set false to disable per-column
textWrap?: boolean // default falseColumn Reset Feature
The reset button (🔄) in the Column Settings dropdown provides a comprehensive "factory reset" for all column configurations:
What gets reset:
- ✅ Column order → Original sequence from
columnsprop - ✅ Column visibility → All columns visible (unless
visible: falsein definition) - ✅ Column widths → Original widths from column definitions
- ✅ Frozen columns → No frozen columns (unless
frozen: truein definition) - ✅ Text wrapping → Original wrapping settings from column definitions
- ✅ localStorage → Completely cleared for fresh start
How to use:
- Click "Columns" button in table toolbar
- Click the 🔄 icon in the top-right of the dropdown
- All settings reset instantly
Perfect for:
- User training and onboarding
- Testing and debugging
- User support scenarios
- Starting fresh between analysis sessions
Persistence & localStorage
The DataTable automatically persists user settings to localStorage for a seamless experience across page reloads.
Automatic Persistence
By default, the following settings are automatically saved and restored:
- ✅ Column Visibility - Show/hide column states
- ✅ Column Order - Custom column reordering
- ✅ Column Widths - Resized column dimensions
- ✅ Frozen Columns - Column freeze states
- ✅ Text Wrapping - Column text wrapping preferences
- ✅ Filters - Active column filters and global search
- ✅ Sorting - Sort configuration (single or multi-column)
- ✅ Pagination - Current page and page size
Table Identification
Each table needs a unique identifier to prevent localStorage conflicts:
<DataTable
columns={columns}
data={data}
tableId="my-unique-table-id" // Required for persistence
/>localStorage Key Format:
algodomain-smart-dt-{tableId}-{columnHash}Example: algodomain-smart-dt-user-table-abc123def456
Persistence Controls
Fine-tune what gets persisted with granular controls:
<DataTable
columns={columns}
data={data}
tableId="my-table"
enablePersistence={true} // Master switch (default: true)
persistFilters={true} // Persist filters & search (default: true)
persistSorting={true} // Persist sort config (default: true)
persistColumnSettings={true} // Persist column settings (default: true)
/>Disabling Persistence
// Disable all persistence
<DataTable
columns={columns}
data={data}
enablePersistence={false}
/>
// Selective persistence
<DataTable
columns={columns}
data={data}
tableId="my-table"
persistFilters={false} // Don't persist filters
persistSorting={false} // Don't persist sorting
persistColumnSettings={true} // But do persist column settings
/>Multi-Table Applications
When using multiple DataTables in the same application, each needs a unique tableId:
<DataTable
columns={userColumns}
data={users}
tableId="users-table" // Unique ID
/>
<DataTable
columns={orderColumns}
data={orders}
tableId="orders-table" // Different unique ID
/>localStorage Management
The DataTable handles localStorage operations with error handling:
- Automatic cleanup when localStorage is full
- Graceful fallback if localStorage access fails
- Cross-tab synchronization for real-time updates
- Data validation to prevent corruption
Reset and Clear
Use the 🔄 reset button in Column Settings to:
- Reset all column settings to defaults
- Clear localStorage data for fresh start
- Restore original table configuration
Fixed Headers and Table Height
- Provide
maxHeight(e.g.,"400px"or"50vh") to enable sticky headers with a scrollable body. - Horizontal scroll sync is handled between header and body for a smoother UX.
<DataTable
columns={columns}
data={myTasks}
maxHeight="400px"
/>Styling
- Uses Tailwind design tokens bound to CSS variables in your app's
index.css(or Tailwind entry). - Key visual options:
showColumnBorders: dashed/dotted borders for dense data setsheaderBackgroundColor: customize header background (non-Tailwind inline color supported) - DEPRECATED: usetheme.header.backgroundColorinsteadclassName: apply additional Tailwind classestheme: comprehensive theme configuration for custom styling
Basic Styling
<DataTable
columns={columns}
data={myTasks}
showColumnBorders
headerBackgroundColor="#f8f9fa" // Legacy prop - still works
className="p-4"
/>Custom Theme Styling
The new theme prop provides comprehensive styling control with support for both hex codes and Tailwind classes. This powerful system allows you to customize every aspect of the table's appearance while maintaining full backward compatibility.
Basic Theme Example:
<DataTable
columns={columns}
data={myTasks}
theme={{
header: {
backgroundColor: '#add8e6', // Light blue header (hex)
textColor: 'text-gray-900' // Dark text (Tailwind class)
},
rows: {
backgroundColor: '#FFFFC5', // Light yellow rows (hex)
hoverBackgroundColor: 'hover:bg-blue-50', // Hover effect (Tailwind)
selectedBackgroundColor: '#e6f3ff' // Selected rows (hex)
},
container: {
borderRadius: 'rounded-lg', // Tailwind class
boxShadow: '0 4px 6px -1px rgba(0, 0, 0, 0.1)' // CSS shadow
}
}}
/>Complete Theme Examples
Corporate Theme:
<DataTable
theme={{
header: {
backgroundColor: '#1e40af', // Blue header
textColor: 'text-white', // White text
borderColor: 'border-blue-600'
},
rows: {
backgroundColor: '#f8fafc', // Light gray rows
hoverBackgroundColor: 'hover:bg-blue-50', // Subtle blue hover
selectedBackgroundColor: '#dbeafe', // Light blue selection
alternateRowBackgroundColor: '#f1f5f9' // Striped rows
},
container: {
borderStyle: 'border-solid',
borderColor: 'border-gray-200',
borderRadius: 'rounded-lg',
boxShadow: '0 1px 3px 0 rgba(0, 0, 0, 0.1)'
},
columns: {
borderColor: 'border-gray-100',
separatorColor: '#e5e7eb'
}
}}
/>Modern Dark Theme:
<DataTable
theme={{
header: {
backgroundColor: '#374151', // Dark gray header
textColor: 'text-white',
borderColor: 'border-gray-600'
},
rows: {
backgroundColor: '#1f2937', // Dark rows
hoverBackgroundColor: 'hover:bg-gray-700',
selectedBackgroundColor: '#4b5563',
textColor: 'text-gray-100'
},
container: {
backgroundColor: '#111827',
borderStyle: 'border-solid',
borderColor: 'border-gray-600',
borderRadius: 'rounded-xl',
boxShadow: '0 10px 15px -3px rgba(0, 0, 0, 0.3)'
},
controls: {
backgroundColor: '#374151',
textColor: 'text-gray-200',
buttonBackgroundColor: '#4b5563',
buttonHoverBackgroundColor: '#6b7280'
}
}}
/>Border Style Examples
No Border (Clean Look):
<DataTable
theme={{
container: {
borderStyle: 'border-none',
boxShadow: '0 4px 6px -1px rgba(0, 0, 0, 0.1)' // Add shadow for definition
}
}}
/>Dashed Border:
<DataTable
theme={{
container: {
borderStyle: 'border-dashed',
borderColor: 'border-blue-300'
}
}}
/>Dotted Border:
<DataTable
theme={{
container: {
borderStyle: 'border-dotted',
borderColor: 'border-red-400'
}
}}
/>Double Border:
<DataTable
theme={{
container: {
borderStyle: 'border-double',
borderColor: 'border-purple-500'
}
}}
/>Custom CSS Border:
<DataTable
theme={{
container: {
borderStyle: '3px solid',
borderColor: '#ff0000'
}
}}
/>Mixed Border Styles:
<DataTable
theme={{
container: {
borderStyle: '2px dashed',
borderColor: '#10b981', // Green dashed border
borderRadius: 'rounded-2xl',
padding: '16px'
},
columns: {
borderStyle: 'border-solid',
borderColor: 'border-gray-200'
}
}}
/>Advanced Theme Combinations
Minimalist Theme:
<DataTable
theme={{
header: {
backgroundColor: 'bg-transparent',
textColor: 'text-gray-700',
borderColor: 'border-transparent'
},
rows: {
backgroundColor: 'bg-transparent',
hoverBackgroundColor: 'hover:bg-gray-50',
borderColor: 'border-transparent'
},
container: {
borderStyle: 'border-none',
backgroundColor: 'bg-transparent'
}
}}
/>High Contrast Theme:
<DataTable
theme={{
header: {
backgroundColor: '#000000',
textColor: '#ffffff',
borderColor: '#ffffff'
},
rows: {
backgroundColor: '#ffffff',
hoverBackgroundColor: '#f0f0f0',
selectedBackgroundColor: '#e0e0e0',
textColor: '#000000',
borderColor: '#000000'
},
container: {
borderStyle: 'border-solid',
borderColor: '#000000',
borderRadius: 'rounded-none'
}
}}
/>Theme Configuration Options
interface DataTableTheme {
header?: {
backgroundColor?: string; // hex like '#f8f9fa' or Tailwind like 'bg-blue-100'
textColor?: string; // hex or Tailwind like 'text-gray-900'
borderColor?: string; // hex or Tailwind like 'border-gray-200'
borderStyle?: string; // CSS border style like '1px solid'
};
rows?: {
backgroundColor?: string; // default row background
hoverBackgroundColor?: string; // hover state
selectedBackgroundColor?: string; // selected row background
alternateRowBackgroundColor?: string; // for striped tables
textColor?: string;
borderColor?: string;
borderStyle?: string;
};
container?: {
backgroundColor?: string;
borderColor?: string; // hex like '#ff0000' or Tailwind like 'border-red-500'
borderStyle?: string; // Tailwind like 'border-dashed', 'border-dotted', 'border-none' or CSS like '1px solid'
borderRadius?: string; // hex or Tailwind like 'rounded-lg'
padding?: string; // CSS padding
boxShadow?: string; // CSS shadow
};
columns?: {
borderColor?: string;
borderStyle?: string;
separatorColor?: string; // for column separators
};
controls?: {
backgroundColor?: string;
textColor?: string;
buttonBackgroundColor?: string;
buttonHoverBackgroundColor?: string;
borderColor?: string;
};
}Theme Best Practices
Color Input Types:
- Hex Colors: Use for exact color control (
#ff0000,#3b82f6) - Tailwind Classes: Use for design system consistency (
bg-blue-500,text-gray-900) - CSS Values: Use for custom properties (
rgb(255, 0, 0),rgba(0, 0, 0, 0.5))
Border Style Guidelines:
- Tailwind Classes:
border-none,border-dashed,border-dotted,border-double,border-solid - CSS Values:
1px solid,2px dashed,3px dotted - Mixed Usage: Combine Tailwind for style, hex for color (
borderStyle: 'border-dashed'+borderColor: '#ff0000')
Performance Tips:
- Use Tailwind classes when possible for better CSS optimization
- Prefer hex colors for brand-specific colors
- Use CSS values for precise control (shadows, padding, margins)
Accessibility Considerations:
- Ensure sufficient color contrast ratios (WCAG AA: 4.5:1, AAA: 7:1)
- Test with dark and light themes
- Consider color-blind users when choosing color combinations
Troubleshooting Theme Issues
Common Issues and Solutions:
Styles Not Applying:
// ❌ Wrong - theme structure theme={{ headerBgColor: '#ff0000' // Wrong property name }} // ✅ Correct - use proper structure theme={{ header: { backgroundColor: '#ff0000' } }}Border Styles Not Working:
// ❌ Wrong - invalid border style theme={{ container: { borderStyle: 'dashed' // Missing 'border-' prefix } }} // ✅ Correct - use proper Tailwind class theme={{ container: { borderStyle: 'border-dashed' } }}Colors Not Showing:
// ❌ Wrong - invalid color format theme={{ header: { backgroundColor: 'blue' // Not a valid CSS color } }} // ✅ Correct - use hex or Tailwind theme={{ header: { backgroundColor: '#3b82f6' // Hex color // OR backgroundColor: 'bg-blue-500' // Tailwind class } }}Selected Row Colors Not Working:
// ✅ Ensure selection is enabled <DataTable enableSelection={true} selectionMode="multiple" theme={{ rows: { selectedBackgroundColor: '#e6f3ff' } }} />
Backward Compatibility
The new theme system is fully backward compatible:
- Existing
headerBackgroundColorprop continues to work - All default styles remain unchanged
- Theme values override legacy props when both are provided
Migration Guide:
// Old way (still works)
<DataTable
headerBackgroundColor="#f8f9fa"
/>
// New way (recommended)
<DataTable
theme={{
header: {
backgroundColor: '#f8f9fa'
}
}}
/>
// Both together (theme takes precedence)
<DataTable
headerBackgroundColor="#f8f9fa" // Legacy prop
theme={{
header: {
backgroundColor: '#add8e6' // This will be used
}
}}
/>Backend Integration with ORM Adapters
Use backendORM to shape the POST request payload into the format expected by your backend:
custom(default): pass-through{ page, pageSize, sort, filters, logicalOperator }.prisma: builds{ where, orderBy, skip, take }with proper Prisma query format and global search support.mongoose: builds{ filter, sort, skip, limit }with$and/$orchains and regex for text.typeorm: builds{ where, order, skip, take }using a neutral, mappable format.
Example (server mode):
<DataTable
columns={columns}
api={{ endpoint: "/api/tasks" }}
mode="server"
backendORM="mongoose"
initialPageSize={25}
/>Server responsibilities:
- Accept POST requests with the transformed payload.
- Apply filtering, sorting, and pagination.
- Return a JSON response matching
{ data, totalRecords, page, pageSize, totalPages }.
Prisma Backend Setup
For Prisma ORM, your backend should handle the transformed payload:
// Example Prisma backend endpoint
export const searchOrders = async (req, res, next) => {
try {
// DataTable sends the complete Prisma query object
const prismaQuery = req.body; // { where, orderBy, skip, take }
// Execute the Prisma query
const result = await prisma.customerOrder.findMany(prismaQuery);
// Get total count for pagination
const { where } = prismaQuery;
const total = await prisma.customerOrder.count({ where });
// Calculate pagination info
const skip = prismaQuery.skip || 0;
const take = prismaQuery.take || 10;
const page = Math.floor(skip / take) + 1;
const totalPages = Math.ceil(total / take);
res.json({
data: result,
totalRecords: total,
page: page,
pageSize: take,
totalPages: totalPages
});
} catch (error) {
next(error);
}
};Route Setup:
// Detect DataTable requests by Prisma format
router.post('/', (req, res, next) => {
if (req.body.skip !== undefined || req.body.take !== undefined ||
req.body.where !== undefined || req.body.orderBy !== undefined) {
return searchOrders(req, res, next);
}
// Handle other POST requests...
});Error Handling
- If the server responds with a non-OK status, an error message is shown in-table.
- Provide
onErrorto handle errors globally (e.g., toast notifications).
onError={(err) => {
console.error("DataTable error", err)
}}Performance Tips
- Prefer server or auto mode for very large datasets.
- Use
filterType: "select"for categorical columns to reduce user input and improve clarity. - Provide
dataTypefor accurate operators and comparisons. - Consider virtualizing rows for extremely large client datasets (outside this component).
Full Minimal Examples
Client with data prop (minimal):
<DataTable columns={columns} data={myTasks} />Client with API endpoint (minimal):
<DataTable columns={columns} api={{ endpoint: "/api/tasks" }} mode="client" />Server (minimal):
<DataTable columns={columns} api={{ endpoint: "/api/tasks" }} mode="server" />Auto (minimal):
<DataTable columns={columns} api={{ endpoint: "/api/tasks" }} mode="auto" />Reference
Complete Properties Reference
| Property | Type | Required | Default | Description | Dependencies & Notes |
|----------|------|----------|---------|-------------|---------------------|
| Data Configuration |
| columns | ColumnDef<T>[] | ✅ Required | - | Column definitions for the table | Must be provided |
| data | T[] | ⚠️ Conditional | - | Data array for client mode | Required if mode is "client" or undefined (but not with api) |
| api | APIConfig | ⚠️ Conditional | - | API configuration for data fetching | Required if mode is "server" or "auto"; optional for mode="client" |
| backendORM | "custom" \| "prisma" \| "mongoose" \| "typeorm" | ❌ Optional | "custom" | Backend ORM adapter for request shaping | Only used in server/auto modes |
| Table Identification |
| tableId | string | ❌ Optional | Auto-generated | Unique identifier for localStorage | Auto-generated from column IDs if not provided |
| Pagination |
| mode | "client" \| "server" \| "auto" | ❌ Optional | undefined (client) | Data handling mode | Determines which other props are required |
| serverPageSize | number | ❌ Optional | 100 | Page size for server requests | Only used in server/auto modes |
| pageSizeOptions | number[] | ❌ Optional | [10, 20, 50, 100, 500] | Available page size options | Used for page size selector |
| initialPageSize | number | ❌ Optional | First from pageSizeOptions | Initial page size | Must be one of the values in pageSizeOptions |
| Selection |
| enableSelection | boolean | ❌ Optional | false | Enable row selection | - |
| selectionMode | "single" \| "multiple" | ❌ Optional | "single" | Selection behavior | Requires enableSelection={true} |
| enableRowCounts | boolean | ❌ Optional | false | Displays a numbering column | Appears before selection column and follows pagination |
| onSelectionChange | (rows: T[]) => void | ❌ Optional | - | Selection change callback | Recommended when using selection |
| Filtering |
| enableFiltering | boolean | ❌ Optional | true | Enable column filtering | - |
| enableGlobalSearch | boolean | ❌ Optional | true | Enable global search | - |
| savedFilters | SavedFilter[] | ❌ Optional | [] | Pre-defined saved filters | - |
| onSaveFilter | (filter: SavedFilter) => void | ❌ Optional | - | Save filter callback | Recommended when using saved filters |
| Sorting |
| enableSorting | boolean | ❌ Optional | true | Enable column sorting | - |
| enableMultiSort | boolean | ❌ Optional | true | Enable multi-column sorting | Requires enableSorting={true} |
| Column Management |
| enableColumnVisibility | boolean | ❌ Optional | true | Show/hide columns | - |
| enableColumnReorder | boolean | ❌ Optional | false | Drag to reorder columns | - |
| enableColumnResize | boolean | ❌ Optional | false | Resize columns by dragging | - |
| enableColumnFreeze | boolean | ❌ Optional | false | Freeze columns left/right | - |
| enableHeaderFreeze | boolean | ❌ Optional | true | Enable sticky headers | - |
| Caching |
| cacheTimeout | number | ❌ Optional | 300000 (5 min) | Cache timeout in milliseconds | Only used in auto mode |
| maxCacheSize | number | ❌ Optional | 1000 | Maximum cached records | Only used in auto mode |
| enablePrefetch | boolean | ❌ Optional | false | Prefetch next pages | Only used in auto mode |
| Persistence |
| enablePersistence | boolean | ❌ Optional | true | Enable localStorage persistence | Master switch for all persistence |
| persistFilters | boolean | ❌ Optional | true | Persist filters and search | Requires enablePersistence={true} |
| persistSorting | boolean | ❌ Optional | true | Persist sort configuration | Requires enablePersistence={true} |
| persistColumnSettings | boolean | ❌ Optional | true | Persist column settings | Requires enablePersistence={true} |
| Styling |
| className | string | ❌ Optional | - | Additional CSS classes | Applied to table container |
| density | "compact" \| "normal" \| "comfortable" | ❌ Optional | "normal" | Row density | Affects row height and spacing |
| showColumnBorders | boolean | ❌ Optional | false | Show column borders | - |
| maxHeight | string \| number | ❌ Optional | - | Maximum table height | Enables sticky headers automatically |
| headerBackgroundColor | string | ❌ Optional | "#f8f9fa" | Header background color | CSS color value |
| Grid View |
| enableGridView | boolean | ❌ Optional | false | Enable grid/table toggle | Requires renderGridItem to be provided |
| renderGridItem | (row: T) => React.ReactNode | ⚠️ Conditional | - | Custom card renderer function | Required when enableGridView={true} |
| Events |
| onRowClick | (row: T) => void | ❌ Optional | - | Row click handler | - |
| onError | (error: Error) => void | ❌ Optional | - | Error handler | Recommended for production |
Property Dependencies & Requirements
Mode-Specific Requirements
Client Mode (mode="client" or undefined):
- ✅
columns(required) - ✅
dataORapi(one required, but not both) - ❌ Cannot use both
dataandapisimultaneously
Server Mode (mode="server"):
- ✅
columns(required) - ✅
api(required) - ❌
data(not used)
Auto Mode (mode="auto"):
- ✅
columns(required) - ✅
api(required) - ❌
data(not used)
Conditional Requirements
Selection Features:
selectionModerequiresenableSelection={true}onSelectionChangerecommended when using selection
Multi-Column Sorting:
enableMultiSortrequiresenableSorting={true}
Persistence Features:
persistFilters,persistSorting,persistColumnSettingsrequireenablePersistence={true}
Caching Features (Auto mode only):
cacheTimeout,maxCacheSize,enablePrefetchonly apply in auto mode
Grid View Features:
renderGridItemis required whenenableGridView={true}- Grid view defaults to active on mobile (< 768px) when enabled
- View mode preference is persisted per table in localStorage (requires
tableId)
Property Conflicts
Mutually Exclusive:
dataandapicannot both be used in client mode (will show validation error)enablePersistence={false}disables all persistence features regardless of individualpersist*settings
Recommended Combinations:
- Use
tableIdwhenenablePersistence={true}for predictable localStorage keys - Use
onErrorhandler in production applications - Use
onSelectionChangewhenenableSelection={true} - Use
onSaveFilterwhen providingsavedFilters
ColumnDef Properties Reference
| Property | Type | Required | Default | Description | Dependencies & Notes |
|----------|------|----------|---------|-------------|---------------------|
| Basic Configuration |
| id | string | ✅ Required | - | Unique column identifier | Must be unique across all columns |
| header | string | ✅ Required | - | Column header text | Displayed in table header |
| accessorKey | keyof T | ✅ Required | - | Key to access data from row object | Must match property in data objects |
| Customization |
| cell | (row: T) => React.ReactNode | ❌ Optional | - | Custom cell renderer | Receives full row object for rendering |
| Functionality |
| sortable | boolean | ❌ Optional | true | Enable sorting for this column | Requires enableSorting={true} on DataTable |
| filterable | boolean | ❌ Optional | true | Enable filtering for this column | Requires enableFiltering={true} on DataTable |
| dataType | "string" \| "number" \| "date" \| "boolean" | ❌ Optional | Auto-detected | Data type for filtering/sorting | Used for proper filter operators |
| filterType | "text" \| "number" \| "date" \| "select" \| "boolean" | ❌ Optional | Based on dataType | Filter input type | Determines filter UI component |
| filterOptions | { label: string; value: unknown }[] | ⚠️ Conditional | - | Options for select filter | Required when filterType="select" |
| Sizing |
| width | number | ❌ Optional | 150 | Column width in pixels | Used for initial column width |
| minWidth | number | ❌ Optional | 80 | Minimum column width | Prevents columns from becoming too narrow |
| maxWidth | number | ❌ Optional | 500 | Maximum column width | Prevents columns from becoming too wide |
| resizable | boolean | ❌ Optional | true | Allow column resizing | Requires enableColumnResize={true} on DataTable |
| Visibility & Layout |
| visible | boolean | ❌ Optional | true | Initial column visibility | Can be changed by user if enableColumnVisibility={true} |
| frozen | boolean | ❌ Optional | false | Freeze column to left/right | Requires enableColumnFreeze={true} on DataTable |
| frozenPosition | "left" \| "right" | ❌ Optional | "left" | Position for frozen columns | Only applies when frozen={true} |
| textWrap | boolean | ❌ Optional | false | Enable text wrapping in cells | Controls text overflow behavior |
ColumnDef Dependencies & Requirements
Conditional Requirements
Filter Configuration:
filterOptionsis required whenfilterType="select"filterTypeshould matchdataTypefor optimal UX
Sizing Constraints:
minWidthshould be ≤width≤maxWidthwidthshould be within reasonable bounds (50-1000px)
Functionality Dependencies:
- Column sorting requires both
sortable={true}andenableSorting={true}on DataTable - Column filtering requires both
filterable={true}andenableFiltering={true}on DataTable - Column resizing requires both
resizable={true}andenableColumnResize={true}on DataTable - Column freezing requires both
frozen={true}andenableColumnFreeze={true}on DataTable
Best Practices
Column IDs:
- Use descriptive, kebab-case IDs:
"user-name","created-at" - Avoid spaces and special characters
- Keep IDs consistent across different table instances
Data Types:
- Set
dataTypeexplicitly for proper filtering/sorting - Use
"date"for date columns to enable date picker filters - Use
"boolean"for true/false columns
Filter Types:
- Use
"select"for columns with limited, known values - Use
"date"for date columns - Use
"number"for numeric columns - Use
"text"for general string columns
Sizing:
- Set reasonable
widthvalues based on content - Use
minWidthto prevent columns from becoming unusable - Use
maxWidthto prevent columns from taking too much space
Operators:
type FilterOperator =
| "=" | "!=" | "contains" | "startsWith" | "endsWith" | "isEmpty" | "isNotEmpty"
| ">" | "<" | ">=" | "<=" | "between"Quick Reference & Common Patterns
Minimal Client Table (with data prop)
<DataTable
columns={columns}
data={myData}
tableId="simple-table"
/>Minimal Client Table (with API endpoint)
<DataTable
columns={columns}
api={{ endpoint: "/api/data" }}
mode="client"
tableId="api-table"
/>Full-Featured Client Table
<DataTable
columns={columns}
data={myData}
tableId="full-table"
enableRowCounts
enableSelection
selectionMode="multiple"
enableFiltering
enableGlobalSearch
enableSorting
enableMultiSort
enableColumnVisibility
enableColumnReorder
enableColumnResize
enableColumnFreeze
maxHeight="400px"
showColumnBorders
onRowClick={(row) => console.log(row)}
onSelectionChange={(rows) => console.log(rows)}
/>Server Table with Persistence
<DataTable
columns={columns}
api={{ endpoint: "/api/data" }}
mode="server"
tableId="server-table"
backendORM="prisma"
enablePersistence={true}
persistFilters={true}
persistSorting={true}
persistColumnSettings={true}
pageSizeOptions={[10, 25, 50, 100]}
initialPageSize={25}
/>Auto Mode with Caching
<DataTable
columns={columns}
api={{ endpoint: "/api/data" }}
mode="auto"
tableId="auto-table"
serverPageSize={50}
enablePrefetch={true}
cacheTimeout={600000}
maxCacheSize={2000}
/>Disable Persistence
<DataTable
columns={columns}
data={myData}
enablePersistence={false}
// All persistence features disabled
/>Selective Persistence
<DataTable
columns={columns}
data={myData}
tableId="selective-table"
persistFilters={false} // Don't persist filters
persistSorting={false} // Don't persist sorting
persistColumnSettings={true} // But do persist column settings
/>Grid View (Card Layout)
<DataTable
columns={columns}
data={myData}
tableId="grid-table"
enableGridView={true}
renderGridItem={(row) => (
<div className="p-4 border rounded-lg">
<h3 className="font-semibold">{row.title}</h3>
<p className="text-muted-foreground">{row.description}</p>
</div>
)}
enableSelection
selectionMode="multiple"
/>Column Definition Examples
const columns: ColumnDef<Task>[] = [
// Basic column
{
id: "id",
header: "ID",
accessorKey: "id",
width: 80,
},
// Sortable and filterable column
{
id: "title",
header: "Title",
accessorKey: "title",
sortable: true,
filterable: true,
dataType: "string",
filterType: "text",
width: 200,
},
// Select filter column
{
id: "status",
header: "Status",
accessorKey: "status",
dataType: "string",
filterType: "select",
filterOptions: [
{ label: "Active", value: "active" },
{ label: "Inactive", value: "inactive" },
],
},
// Date column with date picker
{
id: "createdAt",
header: "Created At",
accessorKey: "createdAt",
dataType: "date",
filterType: "date",
width: 150,
},
// Custom cell renderer
{
id: "actions",
header: "Actions",
accessorKey: "id",
cell: (row) => (
<button onClick={() => handleEdit(row.id)}>
Edit
</button>
),
sortable: false,
filterable: false,
width: 100,
},
];That's it! You're ready to build powerful, user-friendly tables with client, server, or hybrid workflows.
Dynamic Runtime Controls
The DataTable component supports dynamic runtime control of its features. You can create interactive controls that allow users to enable/disable features on-the-fly without any code changes to the DataTable component itself.
Example: Dynamic Feature Controls
import { useState } from 'react'
import { DataTable, type ColumnDef } from "@algodomain/smart-datatable"
import { Checkbox } from "@/components/ui/checkbox"
interface Task {
id: string
title: string
status: string
}
const columns: ColumnDef<Task>[] = [
{ id: "id", header: "ID", accessorKey: "id" },
{ id: "title", header: "Title", accessorKey: "title" },
{ id: "status", header: "Status", accessorKey: "status" },
]
const data: Task[] = [
{ id: "1", title: "Task 1", status: "Active" },
{ id: "2", title: "Task 2", status: "Completed" },
]
export function DynamicControlsExample() {
// State for dynamic controls
const [controls, setControls] = useState({
enableSelection: true,
enableFiltering: true,
enableGlobalSearch: true,
enableSorting: true,
enableMultiSort: true,
enableColumnVisibility: true,
enableColumnReorder: true,
enableColumnResize: true,
enableColumnFreeze: true,
showColumnBorders: true,
})
const handleControlChange = (control: string, value: boolean) => {
setControls(prev => ({ ...prev, [control]: value }))
}
return (
<div className="space-y-4">
{/* Dynamic Controls */}
<div className="bg-gray-50 p-4 rounded-lg">
<h3 className="font-semibold mb-3">Feature Controls</h3>
<div className="grid grid-cols-2 md:grid-cols-5 gap-4">
<div className="flex items-center space-x-2">
<Checkbox
id="enableSelection"
checked={controls.enableSelection}
onCheckedChange={(checked) => handleControlChange('enableSelection', !!checked)}
/>
<label htmlFor="enableSelection" className="text-sm">Selection</label>
</div>
<div className="flex items-center space-x-2">
<Checkbox
id="enableFiltering"
checked={controls.enableFiltering}
onCheckedChange={(checked) => handleControlChange('enableFiltering', !!checked)}
/>
<label htmlFor="enableFiltering" className="text-sm">Filtering</label>
</div>
<div className="flex items-center space-x-2">
<Checkbox
id="enableGlobalSearch"
checked={controls.enableGlobalSearch}
onCheckedChange={(checked) => handleControlChange('enableGlobalSearch', !!checked)}
/>
<label htmlFor="enableGlobalSearch" className="text-sm">Global Search</label>
</div>
<div className="flex items-center space-x-2">
<Checkbox
id="enableSorting"
checked={controls.enableSorting}
onCheckedChange={(checked) => handleControlChange('enableSorting', !!checked)}
/>
<label htmlFor="enableSorting" className="text-sm">Sorting</label>
</div>
<div className="flex items-center space-x-2">
<Checkbox
id="enableColumnVisibility"
checked={controls.enableColumnVisibility}
onCheckedChange={(checked) => handleControlChange('enableColumnVisibility', !!checked)}
/>
<label htmlFor="enableColumnVisibility" className="text-sm">Column Visibility</label>
</div>
{/* Add more controls as needed */}
</div>
</div>
{/* DataTable with Dynamic Props */}
<DataTable
columns={columns}
data={data}
tableId="dynamic-controls-table"
// Dynamic controls from state
enableSelection={controls.enableSelection}
enableFiltering={controls.enableFiltering}
enableGlobalSearch={controls.enableGlobalSearch}
enableSorting={controls.enableSorting}
enableMultiSort={controls.enableMultiSort}
enableColumnVisibility={controls.enableColumnVisibility}
enableColumnReorder={controls.enableColumnReorder}
enableColumnResize={controls.enableColumnResize}
enableColumnFreeze={controls.enableColumnFreeze}
showColumnBorders={controls.showColumnBorders}
// Fixed properties
selectionMode="multiple"
pageSizeOptions={[5, 10, 20]}
initialPageSize={10}
/>
</div>
)
}Benefits of Dynamic Controls
- User Experience: Allow users to customize their table experience
- Feature Discovery: Help users understand available features
- Flexible Interfaces: Create adaptive UIs that respond to user preferences
- No Code Changes: The DataTable component remains unchanged
- Real-time Updates: Features can be toggled instantly without page refresh
Supported Dynamic Properties
All these properties can be controlled dynamically:
enableSelection- Row selection functionalityenableFiltering- Column filteringenableGlobalSearch- Global search across all columnsenableSorting- Column sortingenableMultiSort- Multi-column sortingenableColumnVisibility- Show/hide columnsenableColumnReorder- Drag to reorder columnsenableColumnResize- Resize columns by draggingenableColumnFreeze- Freeze columns to left/rightshowColumnBorders- Display column borders
Quick Start Page (minimal)
Create a simple page component (e.g., src/pages/ExamplePage.tsx) and paste the following:
import { DataTable, type ColumnDef } from "@algodomain/smart-datatable"
import "@algodomain/smart-datatable/style.css"
type Task = {
id: string
title: string
}
const columns: ColumnDef<Task>[] = [
{ id: "id", header: "ID", accessorKey: "id", sortable: true, filterable: true, dataType: "string" },
{ id: "title", header: "Title", accessorKey: "title", sortable: true, filterable: true, dataType: "string", textWrap: true },
]
const data: Task[] = [
{ id: "1", title: "First task" },
{ id: "2", title: "Second task" },
]
export default function ExamplePage() {
return (
<div className="p-4">
<DataTable
columns={columns}
data={data}
enableFiltering
enableSorting
pageSizeOptions={[5, 10, 20]}
initialPageSize={5}
showColumnBorders
/>
</div>
)
}Make sure your Tailwind entry (e.g., src/index.css) sources the package so class names are included during build:
/* Ensure Tailwind scans DataTable package classes */
@source "../node_modules/@algodomain/smart-datatable/dist/index.js";
/* OR */
@source "../node_modules/@algodomain/smart-datatable/dist/index.cjs";Upcoming
- Authentication support for
mode="server"andmode="auto":- Access token and refresh token handling for secure API requests
- Built-in hooks to inject auth headers in server requests
- Graceful token refresh and retry behavior
- Backward-compatible configuration via new props
