@laterinc/data-table
v0.3.0
Published
Complete data table solution with shadcn/ui and TanStack Table
Maintainers
Readme
@laterinc/data-table
A comprehensive, production-ready data table solution built on TanStack Table and shadcn/ui. This package provides everything you need to build powerful, feature-rich data tables with minimal setup.
✨ Features
- 🎯 Zero Config: Works out of the box with sensible defaults
- 🔧 Fully Customizable: Extensive customization options for advanced use cases
- 📦 All-in-One: Includes TanStack Table, shadcn/ui components, and custom hooks
- 🎨 Beautiful UI: Pre-styled components based on shadcn/ui
- ⚡ Performance: Built with React best practices and optimized for performance
- 🔍 Rich Filtering: Column filters, global search, faceted filters
- 📊 Sorting: Multi-column sorting support
- ✅ Row Selection: Single and multi-row selection
- 📄 Pagination: Client-side and server-side pagination
- 👁️ Column Visibility: Toggle column visibility
- 🎛️ Bulk Actions: Perform actions on multiple rows
- 📱 Responsive: Mobile-friendly design
- 🎭 TypeScript: Fully typed for better DX
📦 Installation
npm install @laterinc/data-table
# or
pnpm add @laterinc/data-table
# or
yarn add @laterinc/data-tablePeer Dependencies
This package requires React 18+ or 19+:
npm install react react-dom🚀 Quick Start
Basic Example
import {
useDataTable,
DataTable,
DataTablePagination,
DataTableColumnHeader,
Checkbox,
type ColumnDef,
} from '@laterinc/data-table';
import '@laterinc/data-table/styles';
type User = {
id: string;
name: string;
email: string;
role: string;
};
const columns: ColumnDef<User>[] = [
{
id: 'select',
header: ({ table }) => (
<Checkbox
checked={table.getIsAllPageRowsSelected()}
onCheckedChange={(value) => table.toggleAllPageRowsSelected(!!value)}
/>
),
cell: ({ row }) => (
<Checkbox
checked={row.getIsSelected()}
onCheckedChange={(value) => row.toggleSelected(!!value)}
/>
),
},
{
accessorKey: 'name',
header: ({ column }) => <DataTableColumnHeader column={column} title="Name" />,
},
{
accessorKey: 'email',
header: 'Email',
},
{
accessorKey: 'role',
header: 'Role',
},
];
function UsersTable({ data }: { data: User[] }) {
const { table } = useDataTable({
columns,
data,
enableRowSelection: true,
enableSorting: true,
enablePagination: true,
});
return (
<div className="space-y-4">
<DataTable table={table} />
<DataTablePagination table={table} />
</div>
);
}Advanced Example with Filters and Bulk Actions
import {
useDataTable,
DataTable,
DataTablePagination,
DataTableFacetedFilter,
DataTableBulkActions,
Input,
type BulkActionDefinition,
} from '@laterinc/data-table';
import { Trash2, Mail } from 'lucide-react';
function AdvancedTable({ data }: { data: User[] }) {
const { table, rowSelection, resetSelection } = useDataTable({
columns,
data,
enableRowSelection: true,
enableSorting: true,
enableFiltering: true,
enablePagination: true,
pageSize: 20,
});
const bulkActions: BulkActionDefinition<User>[] = [
{
label: 'Send Email',
icon: Mail,
onClick: (rows) => {
console.log('Sending email to', rows.length, 'users');
resetSelection();
},
},
{
label: 'Delete',
icon: Trash2,
variant: 'destructive',
onClick: (rows) => {
console.log('Deleting', rows.length, 'users');
resetSelection();
},
},
];
const selectedCount = Object.keys(rowSelection).length;
const selectedRows = table.getFilteredSelectedRowModel().rows;
return (
<div className="space-y-4">
{/* Search */}
<Input
placeholder="Search users..."
value={(table.getColumn('name')?.getFilterValue() as string) ?? ''}
onChange={(e) => table.getColumn('name')?.setFilterValue(e.target.value)}
/>
{/* Filters */}
<div className="flex gap-2">
<DataTableFacetedFilter
column={table.getColumn('role')}
title="Role"
options={[
{ label: 'Admin', value: 'admin' },
{ label: 'User', value: 'user' },
]}
/>
</div>
{/* Bulk Actions */}
{selectedCount > 0 && (
<DataTableBulkActions
selectedCount={selectedCount}
actions={bulkActions}
selectedRows={selectedRows}
/>
)}
{/* Table */}
<DataTable table={table} />
<DataTablePagination table={table} />
</div>
);
}📚 API Reference
Hooks
useDataTable
The main hook for creating a table instance with all features enabled.
const {
table, // TanStack Table instance
rowSelection, // Current row selection state
sorting, // Current sorting state
columnFilters, // Current filter state
columnVisibility, // Current visibility state
pagination, // Current pagination state
resetSelection, // Reset row selection
resetFilters, // Reset all filters
resetSorting, // Reset sorting
resetPagination, // Reset pagination
resetAll, // Reset everything
} = useDataTable({
columns, // Column definitions
data, // Data array
enableRowSelection: true,
enableSorting: true,
enableFiltering: true,
enablePagination: true,
pageSize: 10,
// ... more options
});useServerDataTable
Hook for server-side data tables with manual pagination/sorting/filtering.
const { table, ... } = useServerDataTable({
columns,
data,
rowCount: totalItems, // Total number of items from server
});Components
DataTable
Main table component that renders the table UI.
<DataTable
table={table}
isLoading={false}
emptyState={<CustomEmptyState />}
loadingState={<CustomLoadingState />}
stickyHeader={false}
getRowClassName={(row) => row.isHighlighted ? 'bg-yellow-50' : ''}
/>DataTablePagination
Pagination controls with page size selector.
<DataTablePagination table={table} />DataTableToolbar
Customizable toolbar for filters and actions.
<DataTableToolbar table={table}>
{/* Your custom toolbar content */}
</DataTableToolbar>DataTableFacetedFilter
Multi-select filter for categorical columns.
<DataTableFacetedFilter
column={table.getColumn('status')}
title="Status"
options={[
{ label: 'Active', value: 'active' },
{ label: 'Inactive', value: 'inactive' },
]}
/>DataTableColumnHeader
Sortable column header with sort indicators.
<DataTableColumnHeader column={column} title="Name" />DataTableViewOptions
Column visibility toggle dropdown.
<DataTableViewOptions table={table} />DataTableBulkActions
Bulk action buttons for selected rows.
<DataTableBulkActions
selectedCount={selectedCount}
selectedRows={selectedRows}
actions={[
{
label: 'Delete',
icon: Trash2,
variant: 'destructive',
onClick: (rows) => handleDelete(rows),
},
]}
/>Re-exported from TanStack Table
For convenience, all TanStack Table exports are re-exported:
import {
useReactTable,
getCoreRowModel,
getSortedRowModel,
getFilteredRowModel,
getPaginationRowModel,
flexRender,
type ColumnDef,
type Table,
type Row,
// ... and more
} from '@laterinc/data-table';shadcn/ui Components
All necessary shadcn/ui components are included:
import {
Button,
Checkbox,
Input,
Select,
Badge,
Table,
DropdownMenu,
Popover,
Command,
Tooltip,
Dialog,
Separator,
} from '@laterinc/data-table';🎨 Styling
Import the base styles in your root component:
import '@laterinc/data-table/styles';The package uses Tailwind CSS. Make sure you have Tailwind configured in your project and include the package in your tailwind.config.js:
module.exports = {
content: [
'./src/**/*.{js,ts,jsx,tsx}',
'./node_modules/@laterinc/data-table/**/*.{js,ts,jsx,tsx}',
],
// ... rest of your config
};🔧 TypeScript
The package is fully typed. All types are exported for your convenience:
import type {
ColumnDef,
Table,
Row,
FilterOption,
BulkActionDefinition,
UseDataTableOptions,
} from '@laterinc/data-table';📖 Examples
Check out the /stories directory for more comprehensive examples:
- Basic table with selection
- Advanced table with filtering
- Server-side pagination
- Custom renderers
- Bulk actions
- And more!
🤝 Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
📄 License
MIT © LaterInc
🙏 Credits
Built with:
- TanStack Table - Headless table library
- shadcn/ui - UI components
- Radix UI - Unstyled, accessible components
- Tailwind CSS - Utility-first CSS framework
