nextjs-reusable-table
v4.1.0
Published
A production-ready, highly customizable and reusable table component for Next.js applications. Features include sorting, pagination, search, dark mode, TypeScript support, and zero dependencies.
Maintainers
Keywords
Readme
nextjs-reusable-table
A production-ready, highly customizable and reusable table component for Next.js applications. Built with TypeScript, optimized for performance, and designed with developer experience in mind.
Documentation
| File | Description | |------|-------------| | API.md | Complete prop reference, types, and utility functions | | EXAMPLES.md | Real-world usage patterns and recipes | | TROUBLESHOOTING.md | Common issues, fixes, and FAQ | | CONTRIBUTING.md | How to contribute | | CHANGELOG.md | Version history | | SECURITY.md | Supported versions and vulnerability reporting |
AI Tooling
| File | Description | |------|-------------| | llms.txt | AI-discovery index (llms.txt standard) | | llms-full.txt | Complete inlined reference for AI context windows | | skills/nextjs-reusable-table/SKILL.md | Installable skill for Cursor, Claude Code, and agentskills-compatible editors | | AGENTS.md | AI agent contribution guide | | .cursor/rules/ | Cursor IDE rules (auto-attached per file type) |
Key Features
- Zero Configuration — works out of the box
- Smart Data Handling — auto-formats dates, URLs, arrays
- Built-in Search & Filtering — no extra setup needed
- Fully Responsive — mobile-first design
- Accessible — screen reader friendly with ARIA support
- Dark Mode — automatic system preference detection
- High Performance — optimized renders, ~39KB minified (~12KB gzipped)
- Truly Headless — customize every style, behavior, and interaction via
disableDefaultStyles+customClassNames - CSS Isolated — all styles scoped under
@layer rtblwithrtbl-prefix, zero global style leaking
Installation
npm install nextjs-reusable-table
# or
yarn add nextjs-reusable-table
# or
pnpm add nextjs-reusable-tablePrerequisites
| Requirement | Version | |-------------|---------| | Next.js | 13+ (App Router and Pages Router supported) | | React | 18+ | | React DOM | 18+ | | Tailwind CSS | 3+ or 4+ | | TypeScript | 4.5+ (recommended) |
Note: All components use the
"use client"directive. For SSR contexts, wrap in a client component or usedynamic(() => import(...), { ssr: false }).
Quick Start
"use client";
import { TableComponent } from "nextjs-reusable-table";
import "nextjs-reusable-table/dist/index.css";
interface User {
id: number;
name: string;
email: string;
}
const users: User[] = [
{ id: 1, name: "Alice Johnson", email: "[email protected]" },
{ id: 2, name: "Bob Smith", email: "[email protected]" },
];
export default function UsersTable() {
return (
<TableComponent<User>
columns={["ID", "Name", "Email"]}
data={users}
props={["id", "name", "email"]}
/>
);
}With Search and Pagination
"use client";
import { useState } from "react";
import { TableComponent } from "nextjs-reusable-table";
import "nextjs-reusable-table/dist/index.css";
export default function SearchableTable() {
const [search, setSearch] = useState("");
const [page, setPage] = useState(1);
return (
<div className="space-y-4">
<input
type="text"
placeholder="Search..."
value={search}
onChange={(e) => setSearch(e.target.value)}
className="w-full p-2 border rounded-md"
/>
<TableComponent<User>
columns={["ID", "Name", "Email"]}
data={users}
props={["id", "name", "email"]}
searchValue={search}
enablePagination
page={page}
setPage={setPage}
itemsPerPage={10}
/>
</div>
);
}Tailwind Setup
Tailwind v3 — add to content in tailwind.config.js:
content: [
"./src/**/*.{js,ts,jsx,tsx}",
"./node_modules/nextjs-reusable-table/dist/**/*.{js,mjs}",
]Tailwind v4 — add to your CSS:
@import "tailwindcss";
@source "../node_modules/nextjs-reusable-table/dist";Features
Smart Data Handling
- Dates automatically formatted using
Intl.DateTimeFormat - Arrays displayed as chips with "+X more" expand button
- URLs detected and rendered as
<Link>elements
Column Management
- Sort by specifying
sortablePropsand providing anonSorthandler - Hide/show columns via per-header dropdown (
showRemoveColumns={true})
Action Dropdowns
<TableComponent
actions
actionTexts={["Edit", "Delete"]}
actionFunctions={[
(item) => handleEdit(item),
(item) => handleDelete(item),
]}
/>Custom Cell Rendering
<TableComponent<User>
formatValue={(value, prop, item) => {
if (prop === "status")
return <span className={item.active ? "text-green-600" : "text-red-500"}>{value}</span>;
return value;
}}
/>Headless Mode
<TableComponent
disableDefaultStyles
customClassNames={{
container: "border rounded-xl overflow-hidden",
table: "w-full text-sm",
thead: "bg-slate-100",
th: "px-4 py-3 font-semibold text-left",
tr: "border-b hover:bg-slate-50",
td: "px-4 py-3",
}}
/>For all prop options, see API.md. For more examples, see EXAMPLES.md.
Contributing
Contributions are welcome! See CONTRIBUTING.md for details.
License
ISC — see LICENSE.
Acknowledgments
Inspired by common data table patterns in React and Next.js applications. Thanks to all contributors and users for their support.
