@dataset.sh/data-grid
v0.0.3
Published
A production-grade, feature-rich data grid component for React that serves as a modern replacement for AG Grid
Maintainers
Readme
@dataset.sh/data-grid
A production-grade, feature-rich data grid component library for React that serves as a modern replacement for AG Grid. Built with React, TypeScript, TanStack Table v8, and TanStack Virtual for optimal performance and flexibility.
✨ Features
Core Features
- 🚀 High Performance - Virtual scrolling for both rows and columns, handles 10,000+ rows smoothly
- 📊 Advanced Sorting - Single and multi-column sorting with visual indicators (↑↓)
- 🔍 Smart Filtering - Column-specific filters:
- Text: String contains filter
- Number: Min/max range filter
- Date: Date range picker
- Boolean: Dropdown selector
- 📌 Column Pinning - Pin columns to left or right for always-visible data
- ↔️ Column Resizing - Drag to resize with min/max constraints
- 🔄 Column Reordering - Drag and drop with live preview showing real-time data movement
- ✏️ Cell Editing - Inline editing with built-in and custom editors
- ☑️ Row Selection - None, single, or multi-row selection with checkboxes
- 📱 Responsive - Auto-adapts to container size
- 🎨 Theming - Full CSS variable theming support
Advanced Features
- 🎯 Column Menu - Per-column actions (sort, pin, hide, auto-size)
- 🗂️ Side Panels - Filters panel and columns panel for bulk operations
- 📊 Status Bar - Row count, selection info, and numeric aggregations
- 📋 CSV Export - Export all, filtered, or selected data
- 🔧 Custom Renderers - Custom cell, header, and editor components
- 🎭 Visual Feedback - Hover effects, drag indicators, and drop zones
- ⚡ Optimized Rendering - Only renders visible cells with overscan
🚀 Quick Start
Installation
# Using pnpm (recommended)
pnpm add @dataset.sh/data-grid
# Using npm
npm install @dataset.sh/data-grid
# Using yarn
yarn add @dataset.sh/data-gridBasic Usage
import { DataGrid } from '@dataset.sh/data-grid';
import type { GridColumnDef } from '@dataset.sh/data-grid';
import '@dataset.sh/data-grid/styles';
interface Person {
id: number;
firstName: string;
lastName: string;
age: number;
email: string;
active: boolean;
}
const columns: GridColumnDef<Person>[] = [
{
id: 'select',
headerName: '',
width: 50,
enableSorting: false,
enableFiltering: false,
enableResizing: false,
cell: ({ row }) => (
<input type="checkbox" />
),
},
{
accessorKey: 'id',
headerName: 'ID',
type: 'number',
width: 90,
minWidth: 80,
},
{
accessorKey: 'firstName',
headerName: 'First Name',
type: 'text',
width: 120,
editable: true,
},
{
accessorKey: 'lastName',
headerName: 'Last Name',
type: 'text',
width: 120,
editable: true,
},
{
accessorKey: 'age',
headerName: 'Age',
type: 'number',
width: 80,
},
{
accessorKey: 'email',
headerName: 'Email',
type: 'text',
width: 200,
},
{
accessorKey: 'active',
headerName: 'Active',
type: 'boolean',
width: 100,
},
];
function App() {
const [data] = useState<Person[]>(generateData(1000));
return (
<div style={{ height: '600px' }}>
<DataGrid
data={data}
columns={columns}
selectionMode="multi"
enableColumnReorder
enableColumnResize
sideBar
statusBar
pagination={{
pageSize: 50,
pageSizeOptions: [10, 20, 50, 100],
}}
onStateChange={(state) => {
console.log('Grid state changed:', state);
}}
/>
</div>
);
}📖 API Reference
DataGrid Props
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| data | TData[] | Required | Array of data objects |
| columns | GridColumnDef<TData>[] | Required | Column definitions |
| height | number \| string | '100%' | Grid height |
| width | number \| string | '100%' | Grid width |
| selectionMode | 'none' \| 'single' \| 'multi' | 'none' | Row selection mode |
| enableColumnReorder | boolean | false | Enable column drag and drop |
| enableColumnResize | boolean | false | Enable column resizing |
| sideBar | boolean \| SideBarConfig | false | Show side panel |
| statusBar | boolean \| StatusBarConfig | false | Show status bar |
| pagination | false \| PaginationConfig | false | Pagination configuration |
| rowHeight | number | 40 | Row height in pixels |
| overscanRows | number | 8 | Rows to render outside viewport |
| overscanCols | number | 2 | Columns to render outside viewport |
| onStateChange | (state: GridState) => void | - | State change callback |
| onSelectionChange | (selection: Set<string>) => void | - | Selection change callback |
| getRowId | (row: TData, index: number) => string | - | Custom row ID function |
Column Definition
interface GridColumnDef<TData> {
// Identification
id?: string; // Unique column ID
accessorKey?: keyof TData; // Data property key
// Display
headerName?: string; // Header display text
type?: 'text' | 'number' | 'date' | 'boolean' | 'select';
// Sizing
width?: number; // Initial width
minWidth?: number; // Minimum width (default: 80)
maxWidth?: number; // Maximum width (default: 500)
// Features
enableSorting?: boolean; // Enable sorting (default: true)
enableFiltering?: boolean; // Enable filtering (default: true)
enableResizing?: boolean; // Enable resizing (default: true)
enablePinning?: boolean; // Enable pinning (default: true)
enableReordering?: boolean; // Enable reordering (default: true)
editable?: boolean; // Enable editing (default: false)
// Custom rendering
cell?: (props: { // Custom cell renderer
value: any;
row: TData;
column: Column<TData>;
}) => ReactNode;
header?: (props: { // Custom header renderer
column: Column<TData>;
table: Table<TData>;
}) => ReactNode;
editor?: CellEditor<TData>; // Custom cell editor
// Styling
cellClass?: string | ((row: TData) => string);
headerClass?: string;
}🎨 Features in Detail
Sorting
- Click header to sort ascending → descending → unsorted
- Hold Shift for multi-column sorting
- Visual indicators show sort direction (↑ ascending, ↓ descending)
- Access through column menu or header click
Filtering
Each column type has optimized filter UI:
- Text: Contains filter with text input
- Number: Range filter with min/max inputs
- Date: Date range picker with from/to dates
- Boolean: Dropdown with All/True/False options
Filter features:
- Column header filter button with popover
- Side panel for managing all filters
- Clear individual or all filters
- Visual indicator when filter is active (blue highlight)
Column Operations
Resizing
- Drag column edge to resize
- Respects min/max width constraints
- Visual feedback during resize
- Auto-size option in column menu
Reordering
- Drag column header to reorder
- Live preview: Entire column (header + data) moves in real-time
- Visual feedback:
- Dragged column becomes semi-transparent
- Drop target shows blue highlight
- Blue border indicates drop position
- Move cursor on draggable columns
Pinning
- Pin columns to left or right
- Pinned columns stay visible during horizontal scroll
- Visual separator between pinned and scrollable areas
- Manage through column menu or columns panel
Row Selection
- Checkbox column for multi-select mode
- Click row for single-select mode
- Keyboard support: Shift+click for range selection
- Selection count in status bar
- Export selected rows only
Cell Editing
- Double-click or Enter to edit
- Built-in editors for each column type
- Custom editor support
- Tab/Enter navigation between cells
- Escape to cancel edit
🚀 Performance
Optimized for large datasets with:
- Virtual scrolling: Only renders visible rows/columns
- Memoization: Prevents unnecessary re-renders
- Debounced operations: Filters, resizing
- Efficient state updates: Granular updates
- Lazy rendering: On-demand cell rendering
Tested with 10,000+ rows maintaining 60fps scrolling.
Performance Tips
// For very large datasets (10,000+ rows)
<DataGrid
data={largeData}
columns={columns}
// Increase overscan for smoother scrolling
overscanRows={10}
overscanCols={3}
// Disable features if not needed
enableColumnReorder={false}
// Use fixed row height
rowHeight={40}
// Provide getRowId for efficient updates
getRowId={(row) => row.id}
/>🎨 Theming
Customize appearance with CSS variables:
:root {
/* Colors */
--dg-primary: #2196f3;
--dg-border: #e5e7eb;
--dg-header-bg: #f9fafb;
--dg-row-bg: white;
--dg-row-hover: #f3f4f6;
--dg-row-selected: #eff6ff;
--dg-text: #374151;
--dg-text-secondary: #6b7280;
/* Sizing */
--dg-row-height: 40px;
--dg-header-height: 40px;
--dg-font-size: 14px;
/* Borders */
--dg-border-width: 1px;
--dg-border-style: solid;
/* Animations */
--dg-transition: all 0.2s ease;
}
/* Dark theme example */
[data-theme="dark"] {
--dg-border: #374151;
--dg-header-bg: #1f2937;
--dg-row-bg: #111827;
--dg-row-hover: #1f2937;
--dg-text: #f3f4f6;
}🛠️ Development
If you want to contribute to the library:
# Clone the repository
git clone https://github.com/dataset-sh/datagrid.git
cd datagrid
# Install dependencies
pnpm install
# Start development server
pnpm dev
# Start Storybook
pnpm storybook
# Run tests
pnpm test
# Build library for production
pnpm build:lib
# Type check
pnpm typecheck
# Lint
pnpm lint📦 Package Info
- Package name:
@dataset.sh/data-grid - Repository: https://github.com/dataset-sh/datagrid
- Issues: https://github.com/dataset-sh/datagrid/issues
- License: MIT
🏗️ Architecture
Built with modern React patterns:
- Headless architecture with TanStack Table core
- Composition pattern for extensibility
- Context API for state management
- Virtual scrolling with TanStack Virtual
- Accessible components with Radix UI
- Type-safe with TypeScript
🌐 Browser Support
- Chrome/Edge 90+
- Firefox 88+
- Safari 14+
- Mobile browsers (responsive)
🤝 Contributing
Contributions welcome! Please:
- Fork the repository
- Create a feature branch
- Make your changes
- Add/update tests
- Submit a pull request
📄 License
MIT License - see LICENSE file for details
🙏 Acknowledgments
Built with excellent libraries:
- TanStack Table - Headless table library
- TanStack Virtual - Virtual scrolling
- Radix UI - Accessible UI primitives
- React - UI library
- TypeScript - Type safety
- Vite - Build tool
