Appearance
TablePagination
Reusable pagination component for tables. Works with both client-side and server-side pagination.
Import
tsx
import { TablePagination } from '@/shared/ui/components/table/TablePagination'Props
TablePaginationProps
| Prop | Type | Default | Description |
|---|---|---|---|
| State | |||
pageIndex | number | Required | Current page index (0-based) |
pageSize | number | Required | Current page size |
totalCount | number | - | Total number of items (optional for cursor-based pagination) |
| Options | |||
pageSizeOptions | number[] | [10, 20, 50, 100] | Available page size options |
| Callbacks | |||
onPageChange | (pageIndex: number) => void | - | Called when page changes |
onPageSizeChange | (pageSize: number) => void | - | Called when page size changes |
| Navigation | |||
canPreviousPage | boolean | pageIndex > 0 | Disable previous button |
canNextPage | boolean | true | Disable next button |
| Labels (i18n) | |||
labels | PaginationLabels | - | Custom labels for internationalization |
| Styling | |||
className | string | - | Additional CSS classes |
PaginationLabels
ts
interface PaginationLabels {
rowsPerPage?: string // Default: "Rows per page"
page?: string // Default: "Page"
of?: string // Default: "of"
}Examples
Basic Usage
tsx
import { TablePagination } from '@/shared/ui/components/table/TablePagination'
function MyTable() {
const [pageIndex, setPageIndex] = useState(0)
const [pageSize, setPageSize] = useState(10)
return (
<>
{/* Your table */}
<table>...</table>
{/* Pagination */}
<TablePagination
pageIndex={pageIndex}
pageSize={pageSize}
totalCount={250}
onPageChange={setPageIndex}
onPageSizeChange={(size) => {
setPageSize(size)
setPageIndex(0) // Reset to first page
}}
/>
</>
)
}With Custom Page Sizes
tsx
<TablePagination
pageIndex={pageIndex}
pageSize={pageSize}
totalCount={1000}
pageSizeOptions={[25, 50, 100, 250]}
onPageChange={setPageIndex}
onPageSizeChange={setPageSize}
/>Internationalization
tsx
<TablePagination
pageIndex={pageIndex}
pageSize={pageSize}
totalCount={totalCount}
onPageChange={setPageIndex}
onPageSizeChange={setPageSize}
labels={{
rowsPerPage: 'Filas por página',
page: 'Página',
of: 'de',
}}
/>Server-Side Pagination
tsx
function ServerPaginatedTable() {
const [pageIndex, setPageIndex] = useState(0)
const [pageSize, setPageSize] = useState(10)
const { data, isLoading } = useQuery({
queryKey: ['items', pageIndex, pageSize],
queryFn: () => fetchItems({ page: pageIndex, limit: pageSize }),
})
return (
<>
{isLoading ? <Spinner /> : <Table data={data.items} />}
<TablePagination
pageIndex={pageIndex}
pageSize={pageSize}
totalCount={data?.total}
onPageChange={setPageIndex}
onPageSizeChange={(size) => {
setPageSize(size)
setPageIndex(0)
}}
/>
</>
)
}Cursor-Based Pagination
For cursor-based pagination (no total count):
tsx
function CursorPaginatedTable() {
const [pageIndex, setPageIndex] = useState(0)
const [pageSize, setPageSize] = useState(10)
const { data, hasNextPage, hasPreviousPage } = useCursorPagination({
pageSize,
})
return (
<>
<Table data={data} />
<TablePagination
pageIndex={pageIndex}
pageSize={pageSize}
// No totalCount for cursor-based
canPreviousPage={hasPreviousPage}
canNextPage={hasNextPage}
onPageChange={setPageIndex}
onPageSizeChange={setPageSize}
/>
</>
)
}Controlled Navigation
tsx
function ControlledPagination() {
const [page, setPage] = useState(0)
const [size, setSize] = useState(20)
const totalPages = Math.ceil(totalCount / size)
return (
<TablePagination
pageIndex={page}
pageSize={size}
totalCount={totalCount}
canPreviousPage={page > 0}
canNextPage={page < totalPages - 1}
onPageChange={setPage}
onPageSizeChange={(newSize) => {
setSize(newSize)
// Adjust page if current page would be out of bounds
const newTotalPages = Math.ceil(totalCount / newSize)
if (page >= newTotalPages) {
setPage(newTotalPages - 1)
}
}}
/>
)
}Behavior
Page Index
- 0-based: First page is
0, second page is1, etc. - Automatically calculates total pages from
totalCountandpageSize - Displays as 1-based to users (Page 1, Page 2, etc.)
Page Size Changes
When page size changes:
- Call
onPageSizeChangewith new size - Typically reset to first page (pageIndex = 0)
- Recalculate total pages
tsx
onPageSizeChange={(newSize) => {
setPageSize(newSize)
setPageIndex(0) // Reset to first page
}}Navigation Buttons
- Previous: Disabled when
pageIndex === 0orcanPreviousPage === false - Next: Disabled when on last page or
canNextPage === false - Last page calculated as:
Math.ceil(totalCount / pageSize) - 1
Styling
The component uses Tailwind classes and can be customized:
tsx
<TablePagination
className="mt-6 border-t pt-4"
{...props}
/>Accessibility
- Previous/Next buttons have
aria-labelattributes - Page size select is properly labeled
- Keyboard navigation supported
Integration with DataTable
TablePagination is used internally by DataTable:
tsx
// Inside DataTable component
<TablePagination
pageIndex={table.getState().pagination.pageIndex}
pageSize={table.getState().pagination.pageSize}
totalCount={mode === 'client' ? data.length : totalCount}
pageSizeOptions={pageSizeOptions}
onPageChange={(pageIndex) => table.setPageIndex(pageIndex)}
onPageSizeChange={(pageSize) => table.setPageSize(pageSize)}
canPreviousPage={table.getCanPreviousPage()}
canNextPage={table.getCanNextPage()}
/>