Components
HeroUI v3 Table — data table with sorting, selection, custom cells, expandable rows, pagination, column resizing, empty state and async loading.
npx @21st-dev/cli@beta add hero_ui/heroui-tableLoading preview...
"use client"
import { Table } from "@/components/ui/heroui-table"
import { Pagination } from "@heroui/react"
import { useMemo, useState } from "react"
const columns = [
{ id: "name", name: "Name" },
{ id: "role", name: "Role" },
{ id: "status", name: "Status" },
{ id: "email", name: "Email" },
]
const users = [
{ email: "kate@acme.com", id: 1, name: "Kate Moore", role: "CEO", status: "Active" },
{ email: "john@acme.com", id: 2, name: "John Smith", role: "CTO", status: "Active" },
{ email: "sara@acme.com", id: 3, name: "Sara Johnson", role: "CMO", status: "On Leave" },
{ email: "michael@acme.com", id: 4, name: "Michael Brown", role: "CFO", status: "Active" },
{
email: "emily@acme.com",
id: 5,
name: "Emily Davis",
role: "Product Manager",
status: "Inactive",
},
{ email: "davis@acme.com", id: 6, name: "Davis Wilson", role: "Lead Designer", status: "Active" },
{
email: "olivia@acme.com",
id: 7,
name: "Olivia Martinez",
role: "Frontend Engineer",
status: "Active",
},
{
email: "james@acme.com",
id: 8,
name: "James Taylor",
role: "Backend Engineer",
status: "Active",
},
]
const ROWS_PER_PAGE = 4
export default function PaginationDemo() {
const [page, setPage] = useState(1)
const totalPages = Math.ceil(users.length / ROWS_PER_PAGE)
const pages = Array.from({ length: totalPages }, (_, i) => i + 1)
const paginatedItems = useMemo(() => {
const start = (page - 1) * ROWS_PER_PAGE
return users.slice(start, start + ROWS_PER_PAGE)
}, [page])
const start = (page - 1) * ROWS_PER_PAGE + 1
const end = Math.min(page * ROWS_PER_PAGE, users.length)
return (
<div className="w-full p-8">
<Table>
<Table.ScrollContainer>
<Table.Content aria-label="Table with pagination" className="min-w-[600px]">
<Table.Header columns={columns}>
{(column) => (
<Table.Column isRowHeader={column.id === "name"}>{column.name}</Table.Column>
)}
</Table.Header>
<Table.Body items={paginatedItems}>
{(user) => (
<Table.Row>
<Table.Collection items={columns}>
{(column) => <Table.Cell>{user[column.id as keyof typeof user]}</Table.Cell>}
</Table.Collection>
</Table.Row>
)}
</Table.Body>
</Table.Content>
</Table.ScrollContainer>
<Table.Footer>
<Pagination size="sm">
<Pagination.Summary>
{start} to {end} of {users.length} results
</Pagination.Summary>
<Pagination.Content>
<Pagination.Item>
<Pagination.Previous
isDisabled={page === 1}
onPress={() => setPage((p) => Math.max(1, p - 1))}
>
<Pagination.PreviousIcon />
Prev
</Pagination.Previous>
</Pagination.Item>
{pages.map((p) => (
<Pagination.Item key={p}>
<Pagination.Link isActive={p === page} onPress={() => setPage(p)}>
{p}
</Pagination.Link>
</Pagination.Item>
))}
<Pagination.Item>
<Pagination.Next
isDisabled={page === totalPages}
onPress={() => setPage((p) => Math.min(totalPages, p + 1))}
>
Next
<Pagination.NextIcon />
</Pagination.Next>
</Pagination.Item>
</Pagination.Content>
</Pagination>
</Table.Footer>
</Table>
</div>
)
}
Loading preview...
Loading preview...
Loading preview...
Loading preview...
Loading preview...
Loading preview...
Loading preview...
Loading preview...
Loading preview...