Pagination
Page navigation with a page-size selector, a derived range label, and first / prev / next / last controls. A Lit web component — page state and prev/next are real runtime behavior.
Preview
<esa-pagination total-items="237"></esa-pagination>
<script>
const p = document.querySelector('esa-pagination');
p.pageSizeOptions = [10, 25, 50, 100];
p.addEventListener('pagechange', (e) => console.log(e.detail));
</script> Variants
Compact form — hide the page-size selector and the first/last jump buttons for tighter footers.
<esa-pagination
total-items="80"
page-size="20"
show-page-size-selector="false"
show-first-last-buttons="false"
></esa-pagination> States
Disabled — all controls are dimmed and inert.
<esa-pagination total-items="100" disabled></esa-pagination> API
| Prop | Type | Default | Description |
|---|---|---|---|
total-items | number | 0 | Total number of items across all pages; drives the range label and page count. |
page-size | number | 25 | Items per page. Changing it resets to page 0. |
current-page | number | 0 | Active page, zero-based. |
page-size-options | number[] | [10, 25, 50, 100] | Choices in the page-size selector. Array property — set in JS. |
show-page-size-selector | boolean | true | Toggles the "Items per page" selector. |
show-first-last-buttons | boolean | true | Toggles the first / last jump buttons. |
disabled | boolean | false | Dims and disables all controls. Reflected as an attribute. |
Events
| Event | Type | Default | Description |
|---|---|---|---|
pagechange | CustomEvent | — | Fired when the page changes. detail: { page: number } (zero-based). Bubbles and composed. |
pagesizechange | CustomEvent | — | Fired when the page size changes; page also resets to 0. detail: { pageSize: number }. Bubbles and composed. |
page-size-options is an array property — set it in JS, not as an attribute. The range label is derived as "start – end of total" ("0 of 0" when empty).
Accessibility
- Wraps controls in
role="navigation"witharia-label="Pagination". - Each control button has a descriptive
aria-label(First / Previous / Next / Last page). - The page-size selector is a native labeled
<select>. - Boundary buttons disable at the first/last page rather than wrapping.
Theming surface
Every public token this component reads, extracted from its source at build time.
The Resolves to column walks each token's real lineage —
component → semantic → primitive → raw value — so you
can see exactly where re-pointing it lands. A spoke re-skins by overriding these in
its theme-<slug>.css; component internals are never edited. No
hook for what you need? File it with /request-lego.
| Token | Tier | Resolves to |
|---|---|---|
--focus-ring-color | component | #65ba74 via --color-border-focus → --color-grass-8 |
--focus-ring-width | component | 2px |
--pagination-bg | component | #fcfcfc via --color-surface → --color-gray-1 |
--pagination-button-color | component | #202020 via --color-text-primary → --color-gray-12 |
--pagination-font-size | component | clamp(0.75rem, 0.66rem + 0.44vw, 0.9375rem) via --type-size-200 |
--pagination-padding-x | component | 1rem via --spacing-400 |
--pagination-padding-y | component | 0.5rem via --spacing-200 |
--pagination-text-color | component | #646464 via --color-text-secondary → --color-gray-11 |
--color-border | semantic | #cecece via --color-gray-7 |
--color-disabled-text | semantic | #8d8d8d via --color-gray-9 |
--color-hover-overlay | semantic | rgba(0, 0, 0, 0.03) |
--focus-ring-offset | semantic | 2px |
--font-sans | semantic | 'DM Sans', sans-serif |
--transition-fast | semantic | 150ms ease |
--radius-100 | primitive | 0.25rem |
--radius-full | primitive | 9999px |
--spacing-100 | primitive | 0.25rem |
--spacing-200 | primitive | 0.5rem |
--spacing-400 | primitive | 1rem |