@manggala31/react-datatable
v1.1.0
Published
Production-ready, keyboard-navigable, server-driven Data Table package for React, Inertia.js, and Next.js applications.
Maintainers
Readme
@manggala31/react-datatable
Production-ready, keyboard-navigable, server-driven Data Table package for React, Laravel Inertia.js, and Next.js applications.
Table of Contents
- Overview
- Key Features
- Installation
- Quick Start
- Framework Integrations
- API Reference
- Keyboard Shortcuts
- Styling & Custom Themes
- License
Overview
@manggala31/react-datatable is a high-performance, keyboard-navigable Data Table component designed for enterprise applications. It bridges server-driven query pipelines (such as Laravel DataTables or custom paginated APIs) with a fluid React frontend UI.
Key Features
- Keyboard First Navigation: Select and navigate rows effortlessly using
J/KorDown/Uparrow keys, and activate rows withEnter. - Server Driven Pagination: Designed to work seamlessly with paginated API endpoints, query strings, and Inertia.js props.
- Column Customization: Supports column sorting, custom cell renderers, formatting, and alignment controls.
- Bulk Row Selection: Built-in row checkbox selection state management with bulk action handlers.
- Zero Heavy Dependencies: Built with zero external UI framework dependencies.
- Themeable Architecture: Styled via scoped CSS custom properties, fully compatible with Tailwind CSS.
Installation
# Using npm
npm install @manggala31/react-datatable
# Using yarn
yarn add @manggala31/react-datatable
# Using pnpm
pnpm add @manggala31/react-datatable
# Using bun
bun add @manggala31/react-datatableQuick Start
import React, { useState } from 'react';
import { DataTable, Column } from '@manggala31/react-datatable';
import '@manggala31/react-datatable/styles.css';
interface User {
id: number;
name: string;
email: string;
role: string;
status: 'active' | 'inactive';
}
const columns: Column<User>[] = [
{
key: 'id',
title: 'ID',
sortable: true,
width: '80px',
},
{
key: 'name',
title: 'Full Name',
sortable: true,
},
{
key: 'email',
title: 'Email Address',
sortable: true,
},
{
key: 'role',
title: 'Role',
},
{
key: 'status',
title: 'Status',
render: (user) => (
<span className={`status-badge ${user.status}`}>
{user.status.toUpperCase()}
</span>
),
},
];
const mockData: User[] = [
{ id: 1, name: 'John Doe', email: '[email protected]', role: 'Admin', status: 'active' },
{ id: 2, name: 'Jane Smith', email: '[email protected]', role: 'Editor', status: 'active' },
{ id: 3, name: 'Bob Johnson', email: '[email protected]', role: 'User', status: 'inactive' },
];
export default function UsersTablePage() {
const [selectedRows, setSelectedRows] = useState<User[]>([]);
return (
<div className="container">
<h1>Users Management</h1>
<DataTable<User>
data={mockData}
columns={columns}
rowKey="id"
selectable
onSelectionChange={setSelectedRows}
onRowClick={(row) => console.log('Row clicked:', row)}
/>
</div>
);
}Framework Integrations
Laravel Inertia.js (React)
import React from 'react';
import { router } from '@inertiajs/react';
import { DataTable, Column, PaginationMeta } from '@manggala31/react-datatable';
import '@manggala31/react-datatable/styles.css';
interface Props {
users: {
data: any[];
meta: PaginationMeta;
};
}
export default function UsersIndex({ users }: Props) {
const columns: Column<any>[] = [
{ key: 'id', title: 'ID', sortable: true },
{ key: 'name', title: 'Name', sortable: true },
{ key: 'email', title: 'Email', sortable: true },
{ key: 'created_at', title: 'Joined Date' },
];
const handlePageChange = (page: number) => {
router.get(route('users.index'), { page }, { preserveState: true });
};
const handleSortChange = (sortKey: string, direction: 'asc' | 'desc') => {
router.get(route('users.index'), { sort: sortKey, direction }, { preserveState: true });
};
return (
<DataTable
data={users.data}
columns={columns}
rowKey="id"
pagination={users.meta}
onPageChange={handlePageChange}
onSortChange={handleSortChange}
/>
);
}API Reference
<DataTable> Props
| Prop | Type | Default | Description |
|---|---|---|---|
| data | T[] | Required | Array of row data items. |
| columns | Column<T>[] | Required | Column configuration objects array. |
| rowKey | keyof T \| ((row: T) => string \| number) | Required | Unique key property or getter for row identification. |
| selectable | boolean | false | Enable row checkbox selection column. |
| onSelectionChange | (selectedRows: T[]) => void | undefined | Callback invoked when selected rows change. |
| onRowClick | (row: T) => void | undefined | Callback fired when a row is clicked or activated via Enter key. |
| onPageChange | (page: number) => void | undefined | Callback invoked when pagination page changes. |
| onSortChange | (key: string, direction: 'asc' \| 'desc') => void | undefined | Callback invoked when column sort changes. |
| pagination | PaginationMeta | undefined | Server pagination metadata (total, currentPage, perPage, lastPage). |
Keyboard Shortcuts
| Key | Action |
|---|---|
| J / Down Arrow | Move focus to next row |
| K / Up Arrow | Move focus to previous row |
| Space | Toggle row selection checkbox (when selectable) |
| Enter | Activate selected row (onRowClick) |
Styling & Custom Themes
Default CSS properties can be customized via CSS custom properties:
:root {
--datatable-bg: #ffffff;
--datatable-border: #e2e8f0;
--datatable-text: #0f172a;
--datatable-muted: #64748b;
--datatable-header-bg: #f8fafc;
--datatable-hover-bg: #f1f5f9;
--datatable-selected-bg: #e0e7ff;
--datatable-primary: #6366f1;
}License
MIT License © Ilham Hatta Manggala
