@rozie-ui/pagination-solid
v0.1.7
Published
Idiomatic Solid headless WAI-ARIA pagination control (page-item model with ellipses, sibling/boundary windowing, prev/next, roving keyboard nav) — one accessible Rozie source compiled to Solid.
Maintainers
Readme
@rozie-ui/pagination-solid
Idiomatic solid Pagination — a headless, fully-accessible (WAI-ARIA) pagination control (a windowed page-item model with ellipses, sibling/boundary windowing, prev/next bounds, roving keyboard navigation, and a <nav> landmark) compiled from one Rozie source. It is HEADLESS: expose the page-item model and render each control yourself via the scoped slots, or accept the default token-themed buttons. Every visual value is a CSS custom property, so it re-skins to any design system. This package is generated; do not edit src/ by hand.
Install
npm i @rozie-ui/pagination-solidPeer dependencies: solid-js. Install them alongside this package.
Also installed: @rozie/runtime-solid — Rozie's small, tree-shaken runtime helper package (controllable state, keyboard navigation, event modifiers, and safe interpolation). It arrives as a regular dependency, so npm pulls it for you. Your bundler keeps only the helpers this component actually uses — typically a few hundred bytes to a few KB, minified and gzipped. What's in it and what it costs.
Usage
import { createSignal } from 'solid-js';
import { Pagination } from '@rozie-ui/pagination-solid';
export function Demo() {
const [page, setPage] = createSignal(1);
return (
<Pagination
modelValue={page()}
onModelValueChange={setPage}
total={195}
pageSize={10}
onChange={(e) => console.log('page:', e.page)}
/>
);
}
// Custom page-button content via the itemSlot scoped-slot render prop
// ({ page, selected, goto }). The sibling scoped slots follow the same
// pattern: prevControlSlot, nextControlSlot, ellipsisSlot.
export function CustomItemDemo() {
const [page, setPage] = createSignal(1);
return (
<Pagination
modelValue={page()}
onModelValueChange={setPage}
total={195}
pageSize={10}
itemSlot={(item) => (
<button type="button" aria-current={item.selected ? 'page' : undefined} onClick={item.goto}>
{item.page}
</button>
)}
/>
);
}Theming
Every visual value is a --rozie-pagination-* CSS custom property — override any of them at any ancestor scope. Ready-made design-system bridges ship in the package:
import '@rozie-ui/pagination-solid/themes/shadcn.css'; // or material.css, bootstrap.css, base.cssProps
| Name | Type | Default | Two-way (model) | Required | Description |
| --- | --- | --- | :---: | :---: | --- |
| modelValue | Number | 1 | ✓ | | The 1-based current page (two-way model). Clamped into [1, totalPages]. Bind it with r-model:modelValue / v-model:modelValue / modelValue + onModelValueChange; it is also the Angular ControlValueAccessor control value. |
| totalPages | Number | null | | | Explicit total page count. When provided (> 0) it takes precedence over total + pageSize. Use it when the backend already reports the page count. |
| total | Number | null | | | Total item count. Combined with pageSize to derive the page count (ceil(total / pageSize)) when totalPages is not given. |
| pageSize | Number | null | | | Items per page. Combined with total to derive the page count when totalPages is not given. |
| siblingCount | Number | 1 | | | Number of page buttons shown on each side of the current page (the sibling window). Larger values show more context around the current page. |
| boundaryCount | Number | 1 | | | Number of page buttons always shown at each boundary (the first and last boundaryCount pages), regardless of the current page. |
| disabled | Boolean | false | | | Disable the entire control — every page button and the prev/next controls become non-interactive and are marked aria-disabled. |
| ariaLabel | String | "Pagination" | | | Accessible name for the surrounding <nav> landmark (its aria-label). Defaults to "Pagination". |
Events
| Event | Description |
| --- | --- |
| change | Fired whenever the current page changes (a page button, prev/next, or a programmatic goto/next/prev/first/last). Payload { page } — the new clamped 1-based page. Not fired when the target page equals the current page. |
Imperative handle
Beyond props, the component exposes imperative methods (declared once in the Rozie source via $expose). Grab a handle with the native ref mechanism and call them directly:
| Method | Description |
| --- | --- |
| goto | Go to a specific 1-based page; the argument is clamped into [1, totalPages]. Emits change unless the target equals the current page. |
| next | Advance to the next page (no-op at the last page). Emits change on success. |
| prev | Go back to the previous page (no-op at the first page). Emits change on success. |
| first | Jump to the first page (page 1). Emits change unless already there. |
| last | Jump to the last page (the effective totalPages). Emits change unless already there. |
import { Pagination, type PaginationHandle } from '@rozie-ui/pagination-solid';
let handle: PaginationHandle | undefined;
// The ref callback receives the HANDLE object (not the DOM node).
<Pagination ref={(h) => (handle = h)} modelValue={page()} total={195} pageSize={10} />;
handle?.next();Slots
| Slot | Params | | --- | --- | | prevControl | disabled, goto, page | | ellipsis | index | | item | page, selected, goto | | nextControl | disabled, goto, page |
