A lightweight, flexible, and reusable read-only table component built with React and MUI. Designed for clean UI, performance, and easy integration.
- β‘ Fast and lightweight
- π Strictly read-only (no inline editing)
- π§© Fully reusable
- π Dynamic column definitions
- π Sorting & filtering (optional)
- π Column visibility (optional)
- π Light & Dark theme friendly (CSS variables)
- π€ Export support (optional)
- π§± Fully customizable cells (renderers)
npm install @kumarnishu/basic-react-tableor
yarn add @kumarnishu/basic-react-tableThis example shows how to build a read-only admin table with custom cells using MUI components.
import { useMemo } from "react";
import { Box, Typography, Paper, Chip, IconButton } from "@mui/material";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import {
faPenToSquare,
faTrash,
} from "@fortawesome/free-solid-svg-icons";
import { ReactTable } from "@kumarnishu/basic-react-table";
type Feature = {
id: number;
name: string;
description: string;
group: string;
type: string;
status: "Active" | "Inactive";
};
const features: Feature[] = [
{
id: 1,
name: "User Management",
description: "Manage users and roles",
group: "Admin",
type: "CRUD",
status: "Active",
},
{
id: 2,
name: "Tenant Management",
description: "Handle tenants and domains",
group: "Admin",
type: "CRUD",
status: "Active",
},
{
id: 3,
name: "Reports",
description: "View analytics reports",
group: "Analytics",
type: "View",
status: "Inactive",
},
];
export default function ManageFeaturesPage() {
const columns = useMemo<any[]>(() => [
{
accessorKey: "name",
header: "Feature Name",
},
{
accessorKey: "description",
header: "Description",
Cell: ({ cell }: any) => (
<span style={{ color: "var(--text-muted)" }}>
{cell.getValue()}
</span>
),
},
{
accessorKey: "group",
header: "Group",
Cell: ({ cell }: any) => (
<Chip
label={cell.getValue()}
size="small"
sx={{
backgroundColor: "var(--surface-alt)",
color: "var(--text)",
}}
/>
),
},
{
accessorKey: "type",
header: "Type",
Cell: ({ cell }: any) => (
<Chip
label={cell.getValue()}
size="small"
sx={{
backgroundColor: "var(--primary)",
color: "#fff",
}}
/>
),
},
{
accessorKey: "status",
header: "Status",
Cell: ({ cell }: any) => {
const value = cell.getValue();
return (
<Chip
label={value}
size="small"
sx={{
backgroundColor:
value === "Active"
? "var(--success)"
: "var(--border)",
color: value === "Active" ? "#fff" : "var(--text)",
}}
/>
);
},
},
{
header: "Actions",
Cell: () => (
<Box sx={{ display: "flex", gap: 1 }}>
<IconButton size="small">
<FontAwesomeIcon icon={faPenToSquare} />
</IconButton>
<IconButton size="small">
<FontAwesomeIcon icon={faTrash} />
</IconButton>
</Box>
),
},
], []);
return (
<Box sx={{ p: 2 }}>
<Typography variant="h6" sx={{ mb: 2 }}>
Manage Features
</Typography>
<Paper
elevation={0}
sx={{
backgroundColor: "var(--surface)",
border: "1px solid var(--border)",
}}
>
<ReactTable
columns={columns}
data={features}
enableTopToolbar={true}
pageSize={50}
/>
</Paper>
</Box>
);
}| Prop | Type | Description |
|---|---|---|
| columns | any[] |
Column definitions |
| data | any[] |
Table data |
| pageSize | number |
Rows per page |
| enableTopToolbar | boolean |
Show/hide toolbar |
{
accessorKey: string;
header: string;
Cell?: (props) => ReactNode;
}Uses CSS variables so it automatically adapts to your app theme:
:root {
--surface: #ffffff;
--text: #000000;
--border: #e0e0e0;
}
[data-theme="dark"] {
--surface: #1e1e1e;
--text: #ffffff;
--border: #333;
}You can render anything inside a cell:
- Chips
- Buttons
- Icons
- Custom components
This keeps the table read-only but visually rich.
MIT License
This table is intentionally read-only. Any actions (edit/delete/navigation) should be handled externally via buttons or UI controls inside cells.