@pagination-kit/svelte
v0.1.0
Published
A primitive, headless-friendly pagination component for Svelte 5 — DaisyUI styled, RTL-native, fully overridable via snippets.
Maintainers
Readme
@pagination-kit/svelte
A primitive, headless-friendly pagination component for Svelte 5 (runes).
Styled with DaisyUI + Tailwind CSS v4, native RTL support, and every
part overridable via snippets. Ships as one minified .js file and one
rolled-up .d.ts file — no other runtime dependencies.
- Three variants —
simple(Prev/Next + label) ·numbered·smart(ellipsis-collapsing) - Fully overridable — swap in your own markup for prev/next, a page button, the ellipsis, or the page label via snippets
- Headless-ready — the range-building algorithm, class helpers, and constants are exported so you can build your own UI on top
- Accessible —
aria-current,aria-label,aria-live, properdisabledstates - RTL-native — pass
dir="rtl"; the row and the nav arrows flip automatically - Dark-mode-native — uses DaisyUI semantic color tokens (
base-content,primary, …), so it follows whatever DaisyUI theme is active, light or dark
Install
npm install @pagination-kit/sveltesvelte@^5 is a peer dependency — install it if your project doesn't already
have it. Tailwind CSS v4 + DaisyUI v5 must be configured in the host app,
since this package ships only class names, not CSS.
Quick start
<script lang="ts">
import { Pagination } from '@pagination-kit/svelte';
let page = $state(1);
</script>
<Pagination {page} totalPages={20} onPageChange={(p) => (page = p)} />Props
| Prop | Type | Default | Notes |
| --------------- | ----------------------------------------------------------------------- | -------------- | -------------------------------------------- |
| page | number | — | 1-based current page. Required. |
| totalPages | number | — | Required. Component hides itself when <= 1. |
| onPageChange | (page: number) => void | — | Called on any navigation; not called for a no-op click on the current page. |
| variant | 'simple' \| 'numbered' \| 'smart' | 'smart' | |
| size | 'sm' \| 'md' \| 'lg' | 'md' | |
| color | 'default' \| 'primary' \| 'secondary' \| 'accent' \| 'ghost' \| 'neutral' | 'primary' | DaisyUI semantic color token for the active page. |
| dir | 'ltr' \| 'rtl' | 'ltr' | Flips nav arrows and row order. |
| siblingCount | number | 1 | smart variant only. |
| boundaryCount | number | 1 | smart variant only. |
| ariaLabel | string | 'Pagination' | Label on the <nav> landmark. |
| class | string | — | Extra classes on the row wrapper. |
Snippet overrides
Every rendered piece can be replaced without forking the component:
<Pagination {page} totalPages={20} onPageChange={(p) => (page = p)}>
{#snippet prev({ isFirst })}
<button disabled={isFirst}>← Back</button>
{/snippet}
{#snippet next({ isLast })}
<button disabled={isLast}>Next →</button>
{/snippet}
{#snippet pageButton({ page: p, isCurrent })}
<button aria-current={isCurrent ? 'page' : undefined}>{p}</button>
{/snippet}
{#snippet ellipsis()}
<span>···</span>
{/snippet}
</Pagination>Using icon-based nav buttons (e.g. with lucide-svelte):
<script lang="ts">
import { ChevronLeft, ChevronRight } from 'lucide-svelte';
</script>
<Pagination {page} totalPages={20} onPageChange={(p) => (page = p)}>
{#snippet prev({ isFirst, dir })}
<button disabled={isFirst} aria-label="Previous page">
{#if dir === 'rtl'}<ChevronRight />{:else}<ChevronLeft />{/if}
</button>
{/snippet}
</Pagination>Headless usage
The range-building algorithm and layout primitives are exported directly, so you can build a completely custom UI while reusing the tested logic:
import { buildPageItems, clamp, prevPage, nextPage } from '@pagination-kit/svelte';
buildPageItems({ page: 5, totalPages: 20, siblingCount: 1, boundaryCount: 1 });
// → [{ type: 'page', value: 1 }, { type: 'ellipsis', key: 'ellipsis-start' }, ...]RTL
Pass dir="rtl" and everything flips: the row order reverses and the nav
arrows swap glyphs so "back" always points toward the reading start.
<nav dir="rtl"> also sets the DOM dir attribute, so Tailwind's rtl:
variants and native browser bidi behavior apply to anything you nest inside.
Dark mode
Colors are DaisyUI semantic tokens (bg-primary, text-base-content, etc.),
never hard-coded hex values — the component automatically matches whatever
DaisyUI theme (light or dark) is active on the page, with zero extra props.
License
MIT
