DataGrid
A zero-dependency headless table library for React. Brings sorting, filtering, pagination, and virtual scrolling without imposing any UI opinions.
Why another table library?
Most table libraries bundle UI with logic. You get a styled component that looks fine in a demo and fights you in production. DataGrid separates the two entirely — it handles state and computation, you handle rendering.
import { useDataGrid } from '@ufraan/datagrid';
function UsersTable({ users }: { users: User[] }) {
const { rows, headers, sort, filter } = useDataGrid({
data: users,
columns: [
{ key: 'name', label: 'Name', sortable: true },
{ key: 'email', label: 'Email', sortable: true },
{ key: 'role', label: 'Role', filterable: true },
],
});
return (
<table>
<thead>
<tr>
{headers.map(h => (
<th key={h.key} onClick={() => sort(h.key)}>
{h.label} {h.sorted && (h.sortDir === 'asc' ? '↑' : '↓')}
</th>
))}
</tr>
</thead>
<tbody>
{rows.map(row => (
<tr key={row.id}>
{row.cells.map(cell => <td key={cell.key}>{cell.value}</td>)}
</tr>
))}
</tbody>
</table>
);
}Features
- Sorting — single and multi-column, stable sort
- Filtering — global and per-column, debounced
- Pagination — controlled or uncontrolled
- Virtual scrolling — renders only visible rows for large datasets
- Accessibility — correct ARIA roles, keyboard navigation
- TypeScript — fully typed, generics for row data
Performance
| Rows | Sort (ms) | Filter (ms) | Render (ms) |
|---|---|---|---|
| 1,000 | 2 | 1 | 8 |
| 10,000 | 18 | 6 | 12* |
| 100,000 | 190 | 60 | 14* |
*With virtual scrolling enabled — only visible rows are in the DOM.