Pagination
Pagination controls allow users to navigate through multi-page data sets in tables and lists. Always paired with a record count summary on the left and page buttons on the right.
Overview
Pagination sits inside .table-pagination at the bottom of every .table-wrap. It always shows: a count summary on the left ("Showing 1–20 of 124") and page number buttons on the right. Prev/next arrows flank the numbered buttons.
Variants
Compact Variant
For smaller spaces — prev/next buttons with text labels instead of numbers.
Page 1 of 7
Token Reference
| Part | Class | Value |
|---|---|---|
| Container | .table-pagination | padding:12px 16px, border-top:1px solid #E2E8F0, flex space-between, 12px color:#64748B |
| Page button | .page-btn | 30x30px, radius:8px, border:#E2E8F0, bg:#fff, hover: border+color #6366F1, bg:#EEF2FF |
| Active page | .page-btn.active | bg:#6366F1, border:#6366F1, color:#fff, fw-700 |
| Ellipsis | .page-btn.ellipsis | cursor:default, transparent border/bg. No hover effect. |
| Prev/Next arrows | — | 12x12px SVG chevron icons inside .page-btn |
| Count text | — | 12px, color:#64748B. Numbers in <strong> with color:#0F172A |
| Gap between buttons | — | 4px (flex gap on .page-btns) |
Behavior Rules
| Rule | Detail |
|---|---|
| Always show first and last page | Never hide page 1 or the last page. Use ellipsis (...) for gaps in between. |
| Show max 5 visible pages | prev | 1 | ... | 3 4 5 | ... | 12 | next — around current page |
| Disable prev on page 1 | Add disabled attribute and opacity:0.5; cursor:not-allowed to prev button on first page. |
| Disable next on last page | Same as above for next button on last page. |
| Count summary | Always show "Showing X–Y of Z [items]". Calculate X = (page-1)*pageSize+1, Y = min(page*pageSize, total). |
AI Implementation Notes
For AI coding assistants: Pagination always lives inside
.table-pagination at the bottom of .table-wrap. Active page uses .page-btn.active — bg:#6366F1. Ellipsis buttons use .page-btn.ellipsis — no hover effect. The count summary always uses the pattern "Showing X–Y of Z". For the default page size use 20 rows per page. Prev button is always the leftmost, Next is always rightmost. Both use 12x12px SVG chevron icons.When to Use
Use Pagination when
- Dataset has more than 20 records
- User needs to navigate to specific pages
- Performance requires server-side paging
Don't use Pagination when
- Dataset has fewer than 20 items — show all
- Infinite scroll is used — mutually exclusive
Properties
| Property | Type | Required | Default | Description |
|---|---|---|---|---|
| currentPage | number | required | — | Active page number (1-indexed). |
| totalPages | number | required | — | Total number of pages. |
| pageSize | number | optional | 20 | Records per page. Used to calculate count summary text. |
| totalItems | number | required | — | Total record count for "Showing X-Y of Z" summary. |
| onPageChange | function | required | — | Called with new page number when user navigates. |
Design Decisions
Why always show first and last page?
Users need spatial context — knowing there are 42 pages helps them understand the scale of the dataset. Always showing page 1 and the last page, with ellipsis in between, provides this context without showing all pages. The current page and its neighbors (±1) are always visible for immediate navigation.
Changelog
v1.0.0July 2026Added
- Standard and compact variants
- Always-visible first/last page with ellipsis
- Disabled prev on page 1, disabled next on last page
States
‹
1
2
›
Active page
bg:#6366F1, white text, fw-700
‹
Disabled
opacity:.45, cursor:not-allowed
Accessibility
| Requirement | Implementation |
|---|---|
| aria-label | Add aria-label="Pagination" to the nav wrapper. |
| Page buttons | Each page button: aria-label="Page X" or aria-current="page" on active. |
| Prev/Next | aria-label="Previous page" and aria-label="Next page" on arrow buttons. |
| Disabled | Use disabled attribute on prev when page=1 and next when page=last. |
Composition
Allowed
Bottom of .table-wrap, inside .table-pagination
Count summary text on the left
Page buttons on the right
Forbidden
Standalone without a table
Inside modal or card header
Best Practices
Do
Always show the count summary: "Showing 1-20 of 124 items".
Users need context about dataset size to understand how many pages to expect.
Don't
Show all page numbers without ellipsis for large datasets.
Showing 50+ page buttons overwhelms the UI — use ellipsis pattern.
Related Components
Anatomy
1
Container
div.table-pagination. display:flex, justify-content:space-between, padding:12px 16px, border-top:1px solid #E2E8F0.
2
Count Summary
Left-aligned text. "Showing X-Y of Z [items]". 12px color:#64748B. Numbers wrapped in strong for emphasis.
3
Page Buttons
div.page-btns. flex, gap:4px. Contains prev arrow, numbered pages, ellipsis, next arrow.
4
Page Button
button.page-btn. 30×30px, radius:8px, border:#E2E8F0. Active: bg:#6366F1 color:#fff. Disabled: opacity:.45.
Content Rules
Good count text
Showing 1–20 of 124 users
Names the entity type — users, not "items" or "results"
Bad count text
Page 1
No context about total records or current range