Pagination
Page navigation for long lists
<script>
import { ref } from 'vue'
const page = ref(1)
</script>Usage
Pagination
Navigate through pages of data. page-sizes puts the items-per-page selector inside the pagination, and TxPagination recalculates the page count for the new size; this demo returns to page 1 when the size changes, as the next section explains.
Page size
page-sizes adds a size selector after the page buttons, named by its visible page-size-label, and lays the controls out in one wrapping row. Picking a size emits update:pageSize and pageSizeChange and leaves the page alone, so the host decides where the reader lands; this demo goes back to page 1.
Best Practices
- Prefer
total + pageSizeso the UI can reflect item counts; usetotalPagesonly when the backend cannot return totals. - Keep
currentPageone-based. Initialize the model to1, not0. - Reset
currentPageto1when filters or search terms change and the old page may be out of range. - Reset it on
pageSizeChangetoo: the component only reports the new size, and the rows the reader was looking at have moved. A page past the new count is clamped either way. - Prefer
pageSizesover a size select of your own beside the pagination: it is named by its visible label and sits in the pagination's own row. - Keep pagination adjacent to the list or table it controls.
- Use the
infoslot for localized range copy such as “Viewing 21–40 of 120 items”.
API Reference
Props
| Property | Type | Default | Description |
|---|---|---|---|
| currentPage | Current page | ||
| pageSize | Items per page; pair with v-model:page-size when the reader can change it | ||
| pageSizes | Page-size choices. Supplying them renders a size selector after the page buttons and lays the controls out in one wrapping row; without them the DOM is unchanged. Invalid sizes are dropped, and a pageSize missing from the list joins it | ||
| pageSizeLabel | Visible label in front of the size selector; it also names the selector for assistive technology | ||
| total | - | Total item count; when omitted or 0, page count falls back to totalPages | |
| totalPages | - | Explicit total page count; used when total is not provided | |
| prevIcon | Custom previous icon class consumed by TxIcon; empty uses the bundled SVG chevron | ||
| nextIcon | Custom next icon class consumed by TxIcon; empty uses the bundled SVG chevron | ||
| showInfo | Show total info | ||
| showFirstLast | Show first/last buttons |
Events
| Property | Type | Default | Description |
|---|---|---|---|
| update:currentPage | - | v-model current page update | |
| pageChange | - | Triggered when users navigate to another page | |
| update:pageSize | - | v-model page size update when the reader picks another size; the current page is left as it is | |
| pageSizeChange | - | Triggered when the reader picks another page size |
Slots
| Property | Type | Default | Description |
|---|---|---|---|
| info | - | Custom page info area |
Dashboard Data Operations
Place pagination directly below the table and bind it to the same reactive model as filtering and selection; avoid floating pagination away from the list container.
Data operations panel
Pagination shares the data-region state with DataTable and Skeleton.
Overview
totaltakes precedence for page-count calculation withpageSize;totalPagesis used whentotalis not provided.showFirstLastrenders first/last page jump buttons, and boundary pages disable first/previous or next/last controls.- The active page button exposes
aria-current="page"; previous/next/first/last controls expose readablearia-labelvalues. - Default navigation chevrons are bundled SVGs and do not require host icon generation; custom icon classes still use
TxIcon. - With
pageSizes, adiv.tx-pagination__sizesits between the page list and the info: a visiblespan.tx-pagination__size-labeland an 88pxTxSelectwhose combobox carriesaria-labelledbypointing at that label. The nav gainshas-page-sizeand lays the list, the selector and the info out in one centred row that wraps when narrow. WithoutpageSizes(or with only invalid sizes) none of this renders. - Picking a size emits
update:pageSizeand thenpageSizeChange, and only when the size differs frompageSize.currentPageis left to the host; if the larger size leaves fewer pages than the current one, the existing clamp emitsupdate:currentPagewith the last page. - The page-size selector passes
aria-labelledbydirectly toTxSelect, which forwards it to the combobox from the first render; no DOM-writing ref callback is needed. The on-demand style plugin loads the select's sheets with pagination; manual style imports still needselect/style.cssand its dependencies.
Technologies
- Source:
packages/tuffex/packages/components/src/pagination/src/TxPagination.vueconfirms total/page-size page calculation, ellipsis window generation, boundary guards, first/last controls, info slot props,aria-current, and readable pagination button labels. - Type contracts:
packages/tuffex/packages/components/src/pagination/src/types.tsdefinesPaginationPropsandPaginationEmits. - Verified coverage:
packages/tuffex/packages/components/src/pagination/__tests__/pagination.test.tscovers total-derived pages, ellipsis rendering, active page semantics, blocked out-of-range navigation, first/last controls, boundary disabled states, localized control labels, and custom info slot props.pagination-page-size.test.ts(6 cases) covers the unchanged DOM without validpageSizes, the selector's order and itsaria-labelledbyname, the size events without a page change, no event for the current size, a missingpageSizejoining the options, and av-model:page-sizeround trip where the clamp pulls the page back. - Recommendation: prefer
total + pageSize; usetotalPagesonly when the backend returns a page count without total items.