Skip to content

DataGrid

The main virtualized data grid component. Handles sorting, filtering, flash highlighting, and column management.

Basic Usage

tsx
import { DataGrid } from '@askturret/grid';
import '@askturret/grid/styles.css';

const users = [
  { id: 1, name: 'Alice', email: 'alice@example.com' },
  { id: 2, name: 'Bob', email: 'bob@example.com' },
];

const columns = [
  { field: 'name', header: 'Name' },
  { field: 'email', header: 'Email' },
];

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

Props

PropTypeDefaultDescription
dataT[]requiredData array to display
columnsColumnDef<T>[]requiredColumn definitions
rowKeykeyof T | (row: T) => stringrequiredUnique row identifier
emptyMessagestring'No data'Message when data is empty
compactbooleanfalseReduce row height for dense displays
showFilterbooleanfalseShow filter input
filterPlaceholderstring'Filter...'Filter input placeholder
filterFields(keyof T)[]all columnsFields to search
classNamestring-Additional CSS class
stickyHeaderbooleantrueMake header sticky
virtualizeboolean | 'auto''auto'Force virtualization mode
rowHeightnumber36Row height in pixels
onRowClick(row: T) => void-Row click handler
disableFlashbooleanfalseDisable flash highlighting
resizablebooleanfalseEnable column resizing
reorderablebooleanfalseEnable column reordering
columnWidthsRecord<string, number>-Controlled column widths
onColumnResize(field: string, width: number) => void-Column resize callback
columnOrderstring[]-Controlled column order
onColumnReorder(newOrder: string[]) => void-Column reorder callback
minColumnWidthnumber50Minimum column width
maxColumnWidthnumber500Maximum column width

Column Definition

tsx
interface ColumnDef<T> {
  field: keyof T | string;
  header: string;
  width?: string;
  align?: 'left' | 'right' | 'center';
  sortable?: boolean;
  flashOnChange?: boolean;
  formatter?: (value: unknown, row: T) => ReactNode;
  cellClass?: (value: unknown, row: T) => string;
  resizable?: boolean;
  reorderable?: boolean;
  minWidth?: number;
  maxWidth?: number;
}

Sorting

Click column headers to sort. Columns are sortable by default.

tsx
const columns = [
  { field: 'name', header: 'Name', sortable: true },
  { field: 'price', header: 'Price', sortable: true },
  { field: 'actions', header: 'Actions', sortable: false },
];

Filtering

Enable the filter input with showFilter:

tsx
<DataGrid
  data={users}
  columns={columns}
  rowKey="id"
  showFilter
  filterPlaceholder="Search..."
  filterFields={['name', 'email']} // Only search these fields
/>

The filter uses trigram indexing for fast substring matching on large datasets.

Flash Highlighting

Cells flash green (increase) or red (decrease) when numeric values change:

tsx
const columns = [
  { field: 'symbol', header: 'Symbol' },
  { field: 'price', header: 'Price', flashOnChange: true },
  { field: 'volume', header: 'Volume', flashOnChange: true },
];

Adaptive Mode

Flash highlighting automatically disables when FPS drops below 55 to maintain performance.

Column Resizing

Drag column borders to resize:

tsx
// Uncontrolled
<DataGrid
  data={data}
  columns={columns}
  rowKey="id"
  resizable
/>

// Controlled
const [widths, setWidths] = useState({ name: 200, email: 300 });

<DataGrid
  data={data}
  columns={columns}
  rowKey="id"
  resizable
  columnWidths={widths}
  onColumnResize={(field, width) =>
    setWidths(prev => ({ ...prev, [field]: width }))
  }
/>

Column Reordering

Drag column headers to reorder:

tsx
// Uncontrolled
<DataGrid
  data={data}
  columns={columns}
  rowKey="id"
  reorderable
/>

// Controlled
const [order, setOrder] = useState(['name', 'email', 'age']);

<DataGrid
  data={data}
  columns={columns}
  rowKey="id"
  reorderable
  columnOrder={order}
  onColumnReorder={setOrder}
/>

Virtualization

The grid automatically virtualizes when row count exceeds 100. Force virtualization mode:

tsx
<DataGrid
  data={largeDataset}
  columns={columns}
  rowKey="id"
  virtualize={true}  // Always virtualize
  rowHeight={32}     // Custom row height
/>

Custom Formatters

Format cell values with the formatter prop:

tsx
const columns = [
  { field: 'symbol', header: 'Symbol' },
  {
    field: 'price',
    header: 'Price',
    formatter: (value) => `$${value.toFixed(2)}`,
  },
  {
    field: 'change',
    header: 'Change',
    formatter: (value, row) => (
      <span className={value >= 0 ? 'green' : 'red'}>
        {value >= 0 ? '+' : ''}{value.toFixed(2)}%
      </span>
    ),
  },
];

Cell Classes

Apply conditional classes to cells:

tsx
const columns = [
  {
    field: 'status',
    header: 'Status',
    cellClass: (value) => {
      if (value === 'active') return 'status-active';
      if (value === 'pending') return 'status-pending';
      return '';
    },
  },
];

Row Click Handler

tsx
<DataGrid
  data={users}
  columns={columns}
  rowKey="id"
  onRowClick={(user) => {
    console.log('Selected:', user);
    navigate(`/users/${user.id}`);
  }}
/>

Compact Mode

Reduce row height for dense displays:

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

Released under the MIT License.