A component for navigating paginated data. Combines first/previous/next/last navigation buttons with a page picker select and an optional items-per-page selector. Navigation buttons default to icon-only with visually hidden labels for accessibility.
Built on the framework-agnostic @pindoba/core-pagination (connectPagination) headless core and available for both Svelte and Astro. It also powers the Table footer. The Astro component is interactive out of the box (it self-syncs and emits a pindoba:change event); for full client control, hydrate it on the pagination runtime and drive it with paginationHydration.get(el)?.update({ … }) (@pindoba/astro-pagination/runtime) — onChangePage and the other callbacks go through update().
---
// GENERATED from packages/demos/pagination/default.demo.tsx — edit the source, not this file.
import Pagination from "@pindoba/astro-pagination";
const itemsPerPage = 10;
---
<Pagination
itemsTotal={1000}
itemsPerPage={itemsPerPage}
data-ir-root="pagination/default"
data-ir="1"
/>
<script>
import { hydrate } from "./_client/default.ts";
document
.querySelectorAll('[data-ir-root="pagination/default"]')
.forEach((root) => hydrate([root]));
</script>Show text labels alongside icons on the navigation buttons by setting visuallyHidden: false on any label key. This is useful when space allows or when a more explicit UI is preferred.
---
// GENERATED from packages/demos/pagination/labels.demo.tsx — edit the source, not this file.
import Pagination from "@pindoba/astro-pagination";
const labels = {
first: { visuallyHidden: false },
previous: { visuallyHidden: false },
next: { visuallyHidden: false },
last: { visuallyHidden: false },
};
const itemsPerPage = 10;
---
<Pagination
itemsTotal={100}
itemsPerPage={itemsPerPage}
labels={labels}
data-ir-root="pagination/labels"
data-ir="1"
/>
<script>
import { hydrate } from "./_client/labels.ts";
document
.querySelectorAll('[data-ir-root="pagination/labels"]')
.forEach((root) => hydrate([root]));
</script>Every string the pagination renders is configurable through the labels prop. The control keys take static text (plus visuallyHidden); the two dynamic readouts take either a function of their values or a {placeholder} template string, so any word order works. Omitted keys keep the English defaults.
const labels: PaginationLabels = {
first: { text: "Primeira" }, // default "First" (aria-label, icon-only)
previous: { text: "Anterior" }, // default "Previous"
next: { text: "Próxima" }, // default "Next"
last: { text: "Última" }, // default "Last"
page: { text: "Página" }, // default "Page"
itemsPerPage: { text: "Itens por página" }, // default "Items per page"
// default "{start} - {end} / {total}" → "1 - 10 / 95"
summary: ({ start, end, total }) => `${start}–${end} de ${total}`,
// default "/ {total}" → "/ 10"
pageOf: "de {total}",
};
| Key | Values | Default |
|---|---|---|
summary | start, end, total, page, totalPages | "{start} - {end} / {total}" |
pageOf | page, total (page count, at least 1) | "/ {total}" |
In Astro, prefer template strings for summary and pageOf: the component re-renders those readouts on the client, and functions can’t cross the SSR → client boundary (they’d fall back to English after the first interaction). The Table forwards its labels.pagination here.