BorderedTable
Borders, search, pagination, sortable, row selection (single or multiple + select all).
Tasks
Manage your tasks and progress.
| 1. | Update software | 55% | 55% | 2025-01-05 | ||
| 2. | Clean database | 70% | 70% | 2025-01-12 | ||
| 3. | Cron job running | 30% | 30% | 2025-01-18 | ||
| 4. | Fix bugs | 90% | 90% | 2025-02-01 | ||
| 5. | Deploy staging | 100% | 100% | 2025-02-08 | ||
| 6. | Run migrations | 45% | 45% | 2025-02-14 | ||
| 7. | Sync assets | 20% | 20% | 2025-02-20 | ||
| 8. | Backup data | 80% | 80% | 2025-02-22 | ||
| 9. | Update dependencies | 60% | 60% | 2025-02-24 | ||
| 10. | Refactor module A | 35% | 35% | 2025-02-25 |
BorderedListTable
List-style table with product rows (image, name, price, action). Toolbar, search, pagination, sort, selection, and row actions like BorderedTable.
Products
List of products with search, sort, and pagination.
Product 1
Electronics · SKU-10000
Product 2
Clothing · SKU-10001
Product 3
Home · SKU-10002
Product 4
Sports · SKU-10003
Product 5
Books · SKU-10004
Product 6
Electronics · SKU-10005
Product 7
Clothing · SKU-10006
Product 8
Home · SKU-10007
Product 9
Sports · SKU-10008
Product 10
Books · SKU-10009
VirtualizedDataTable
Toolbar, sortable columns, Options column, row selection (single or multiple + select all). Windowing: only visible rows rendered.
Virtualized table
50 rows · only visible rows rendered
VirtualizedListView
Virtualized list with toolbar, search, and row selection. Product-style rows: image, name, price, action.
Virtualized list
5000 items · only visible rows rendered
Product 1
Electronics · SKU-10000
Product 2
Clothing · SKU-10001
Product 3
Home · SKU-10002
Product 4
Sports · SKU-10003
Product 5
Books · SKU-10004
Product 6
Electronics · SKU-10005
Product 7
Clothing · SKU-10006
Product 8
Home · SKU-10007
Product 9
Sports · SKU-10008
Product 10
Books · SKU-10009
Product 11
Electronics · SKU-10010
Product 12
Clothing · SKU-10011
Product 13
Home · SKU-10012
Product 14
Sports · SKU-10013
Product 15
Books · SKU-10014
Product 16
Electronics · SKU-10015
Product 17
Clothing · SKU-10016
Product 18
Home · SKU-10017
Product 19
Sports · SKU-10018
Product 20
Books · SKU-10019
Product 21
Electronics · SKU-10020
Product 22
Clothing · SKU-10021
Product 23
Home · SKU-10022
Table Skeleton
Loading placeholder for table.
How to use
BorderedTable, BorderedListTable, VirtualizedDataTable, VirtualizedListView, TableSkeleton. Copy the examples below.
1. Import
import {
BorderedTable,
BorderedListTable,
VirtualizedDataTable,
VirtualizedListView,
TableSkeleton,
Button,
IconButton,
} from "@/app/components/ui";
import type {
TableColumn,
BorderedTableActionMenuItem,
BorderedListTableActionMenuItem,
VirtualizedDataTableActionMenuItem,
} from "@/app/components/ui";2. BorderedTable
type TaskRow = { id: number; task: string; progress: number; createdAt: string };
const columns: TableColumn<TaskRow>[] = [
{ id: "task", header: "Task" },
{ id: "progress", header: "Progress", cell: (row) => `${row.progress}%`, sortValue: (row) => row.progress },
{ id: "createdAt", header: "Created" },
];
const actionMenu = (row: TaskRow): BorderedTableActionMenuItem<TaskRow>[] => [
{ label: "Edit", onClick: () => {} },
{ label: "Delete", onClick: () => {}, variant: "danger" },
];
<BorderedTable
columns={columns}
data={data}
getRowKey={(row) => row.id}
actionColumnMenu={actionMenu}
fixedHeader
stripe
sortable
selectable
selectionMode="multiple"
selectedRowKeys={selectedRowKeys}
onSelectionChange={setSelectedRowKeys}
searchKeys={["task"]}
searchPlaceholder="Search"
selectionBar={<><span>{selectedRowKeys.length} selected</span><Button onClick={() => setSelectedRowKeys([])}>Clear</Button></>}
/>3. BorderedListTable
type ProductRow = { id: number; name: string; category: string; price: string };
const actionMenu = (row: ProductRow): BorderedListTableActionMenuItem<ProductRow>[] => [
{ label: "Edit", onClick: () => {} },
{ label: "Delete", onClick: () => {}, variant: "danger" },
];
<BorderedListTable<ProductRow>
data={data}
getRowKey={(row) => row.id}
renderItem={(row) => (
<div className="flex items-center gap-3">
<span>{row.name}</span>
<span>{row.category}</span>
<span>${row.price}</span>
</div>
)}
actionColumnMenu={actionMenu}
searchKeys={["name", "category"]}
selectable
selectionMode="multiple"
selectedRowKeys={selectedRowKeys}
onSelectionChange={setSelectedRowKeys}
stripe
/>4. VirtualizedDataTable
const columns = [
{ key: "engine", header: "Engine", minWidth: "100px" },
{ key: "browser", header: "Browser", minWidth: "120px" },
{ key: "platform", header: "Platform", minWidth: "80px" },
];
<VirtualizedDataTable
columns={columns}
data={data}
getRowKey={(row) => row.id}
containerHeight={320}
title="Virtualized table"
subtitle="Only visible rows rendered"
searchKeys={["engine", "browser"]}
searchPlaceholder="Search"
sortable
selectable
selectionMode="multiple"
selectedRowKeys={selectedRowKeys}
onSelectionChange={setSelectedRowKeys}
actionColumnMenu={(row) => [
{ label: "Edit", onClick: () => {} },
{ label: "Delete", onClick: () => {}, variant: "danger" },
]}
/>5. VirtualizedListView
type Item = { id: number; name: string; category: string; price: string };
<VirtualizedListView<Item>
data={data}
getRowKey={(item) => item.id}
rowHeight={56}
containerHeight={400}
renderItem={(item) => (
<div className="flex items-center gap-3">
<span>{item.name}</span>
<span>{item.category}</span>
<span>${item.price}</span>
</div>
)}
searchKeys={["name", "category"]}
selectable
selectionMode="multiple"
selectedRowKeys={selectedRowKeys}
onSelectionChange={setSelectedRowKeys}
/>6. TableSkeleton
<TableSkeleton rows={5} cols={4} />