React Component

@utiltools/datagrid

A lightweight, TypeScript-first React data grid with sorting, filtering, pagination and row selection.

Installation

$ npm install @utiltools/datagrid

Or use yarn or pnpm:

$ yarn add @utiltools/datagrid

Quick Start

import { DataGrid } from '@utiltools/datagrid';
import type { ColumnDef } from '@utiltools/datagrid';

interface User {
  id: number;
  name: string;
  email: string;
  role: string;
}

function App() {
  const data: User[] = [
    { id: 1, name: 'Alice', email: '[email protected]', role: 'Admin' },
    { id: 2, name: 'Bob', email: '[email protected]', role: 'User' },
  ];

  const columns: ColumnDef<User>[] = [
    { key: 'name',  label: 'Name',  sortable: true, filterable: true },
    { key: 'email', label: 'Email', sortable: true },
    { key: 'role',  label: 'Role',  sortable: true },
  ];

  return (
    <DataGrid
      data={data}
      columns={columns}
      rowKey="id"
      pageSize={10}
      searchable
    />
  );
}

Features

Sorting

Click column headers to sort ascending or descending

Filtering

Column-level filters with global search

Pagination

Built-in pagination with customizable page sizes

Row Selection

Single or multi-row selection with checkboxes

Custom Rendering

Full control over cell rendering with render functions

TypeScript Support

Full type safety with generic row types

Loading States

Built-in loading skeleton UI

Responsive

Works great on mobile and desktop

API Reference

DataGrid Props

PropTypeDefaultDescription
dataTRow[]requiredArray of row objects to display
columnsColumnDef<TRow>[]requiredColumn definitions
rowKeykeyof TRowindexField to use as unique row identifier
pageSizenumber10Number of rows per page
pageSizeOptionsnumber[][10, 25, 50, 100]Available page size options in the dropdown
selectablebooleanfalseEnable row selection checkboxes
stripedbooleanfalseAlternate row background colors
searchablebooleantrueShow global search input in the toolbar
searchPlaceholderstring"Search…"Placeholder text for the global search input
loadingbooleanfalseShow loading skeleton instead of data rows
emptyMessagestring"No data to display."Message shown when data array is empty
classNamestring""Additional CSS classes applied to the outer wrapper
onSelectionChange(keys: Set<string>) => voidundefinedFired whenever the selected row keys change

ColumnDef Type

interface ColumnDef<T> {
  key: keyof T & string;   // must match a property in your row objects
  label: string;           // column header text
  sortable?: boolean;      // enable sort on click (default: false)
  filterable?: boolean;    // show per-column filter input (default: false)
  width?: number;          // fixed pixel width
  minWidth?: number;       // minimum width
  align?: 'left' | 'center' | 'right';
  render?: (value: unknown, row: T, rowIndex: number) => string; // HTML string
  hidden?: boolean;        // exclude from render
}

Examples

Custom Cell Rendering

const columns: ColumnDef<User>[] = [
  {
    key: 'status',
    label: 'Status',
    sortable: true,
    align: 'center',
    // render returns an HTML string
    render: (value) => {
      const color = value === 'Active' ? 'green' : 'gray';
      return `<span style="color:${color};font-weight:600">${value}</span>`;
    },
  },
  {
    key: 'salary',
    label: 'Salary',
    sortable: true,
    align: 'right',
    render: (value) =>
      typeof value === 'number' ? `$${value.toLocaleString()}` : '—',
  },
];

Column Filtering

Set filterable: true on any column to show a filter input beneath its header. Active filters appear as removable chips above the table.

const columns: ColumnDef<User>[] = [
  { key: 'name',       label: 'Name',       sortable: true, filterable: true },
  { key: 'department', label: 'Department', sortable: true, filterable: true },
  { key: 'salary',     label: 'Salary',     sortable: true },
];

// Global search across all columns is on by default.
// Turn it off with searchable={false}
<DataGrid data={data} columns={columns} rowKey="id" searchable />

Row Selection

function MyGrid() {
  const [selected, setSelected] = useState<Set<string>>(new Set());

  return (
    <>
      <p>{selected.size} rows selected</p>
      <DataGrid
        data={data}
        columns={columns}
        rowKey="id"
        selectable
        onSelectionChange={setSelected}
      />
    </>
  );
}

Striped Rows

<DataGrid
  data={data}
  columns={columns}
  rowKey="id"
  striped
/>

Server-side operations

The current version performs all sorting, filtering, and pagination client-side — pass your full dataset as data and the grid handles the rest. Server-side sorting, filtering, and pagination (for very large datasets fetched page-by-page from an API) is planned as a Pro feature in an upcoming release.

Related Packages

Need Help?

Check out the live demo or open an issue on GitHub.