Pagination
A navigation control for paged data. It lives beside a table or
list — never inside it. Controlled by attributes but self-updating: moving
the page updates page
and fires nana-page-change,
so the same component drives client-side slicing and server-side fetching.
Anatomy (recommended default)
html
| 1 | <nana-pagination |
| 2 | page="7" |
| 3 | page-size="20" |
| 4 | total-items="2845" |
| 5 | show-first-last |
| 6 | show-result-count |
| 7 | show-page-size |
| 8 | show-jump |
| 9 | ></nana-pagination> |
Layouts
layout="numbered" — scales to thousands of pages with ellipsis
layout="compact" — tiny footprint for mobile / side panels
layout="simple" — prev / next for docs & articles
html
| 1 | <nana-pagination layout="numbered" show-first-last></nana-pagination> |
| 2 | <nana-pagination layout="compact"></nana-pagination> |
| 3 | <nana-pagination layout="simple"></nana-pagination> |
Variants
default
ghost
filled
soft
pill
html
| 1 | <nana-pagination variant="default"></nana-pagination> |
| 2 | <nana-pagination variant="ghost"></nana-pagination> |
| 3 | <nana-pagination variant="filled"></nana-pagination> |
| 4 | <nana-pagination variant="soft"></nana-pagination> |
| 5 | <nana-pagination variant="pill"></nana-pagination> |
Sizes
sm
md
lg
Live (client-side)
The control emits events; you own the data. Here it slices a 47-item array.
ts
| 1 | const pager = document.querySelector('nana-pagination'); |
| 2 | |
| 3 | // Client-side: slice the array |
| 4 | pager.addEventListener('nana-page-change', (e) => { |
| 5 | const { page } = e.detail; |
| 6 | render(data.slice((page - 1) * pageSize, page * pageSize)); |
| 7 | }); |
| 8 | |
| 9 | // Server-side: refetch |
| 10 | pager.addEventListener('nana-page-change', (e) => { |
| 11 | fetchUsers({ page: e.detail.page, limit: pager.pageSize }).then(render); |
| 12 | }); |
| 13 | |
| 14 | pager.addEventListener('nana-page-size-change', (e) => { |
| 15 | pageSize = e.detail.pageSize; // page resets to 1 automatically |
| 16 | }); |
Import
ts
| 1 | import "@nana-tec/ui-components/pagination"; |
Events
| Event | Detail |
|---|---|
nana-page-change | { page: number } |
nana-page-size-change | { pageSize: number } |
Customization
Pick a variant
and size; to brand the
current page, set the accent variables.
pagination.css css 1 /* Match the current-page accent to your brand (filled / pill variants) */ 2 nana-pagination.brand { 3 --nana-pagination-active-bg: #2563eb; 4 --nana-pagination-active-color: #fff; 5 --nana-pagination-radius: 9999px; 6 }
CSS Variable Description --nana-pagination-radiusCorner radius of the page controls --nana-pagination-active-bgActive page background (filled / pill) --nana-pagination-active-colorActive page text colour (filled / pill)
Part Description navThe controls container ellipsisThe truncation gap (…)
Props
Attribute Type Default Description page number 1 Current page (1-based) page-size number 10 Rows per page total-items number — Total items — derives pages + result count total-pages number — Explicit page count (when total is unknown) variant default | ghost | filled | soft | pill default Visual style layout numbered | compact | simple numbered Structural layout size sm | md | lg md Control size (32 / 40 / 48px) sibling-count number 1 Page numbers either side of current boundary-count number 1 Page numbers pinned at each end show-first-last boolean false Show « First / Last » buttons show-result-count boolean false Show "Showing X–Y of Z" show-page-size boolean false Show the rows-per-page selector show-jump boolean false Show the jump-to-page input page-size-options string "10,25,50,100" Comma-separated page sizes disabled boolean false Disable the whole control
Accessibility
- Rendered as a
nav labelled "Pagination"; the current page carries aria-current="page". - Each page button has a descriptive label ("Go to page 5"); arrows are labelled "Previous/Next/First/Last page".
- Keyboard: Tab to focus, Enter/Space to activate, and
←/→ to step pages.