Keyboard
No component-specific keymap. Inherits standard browser focus / activation behaviour.
Svelte 5 {@attach} factories. Glue ARIA / keyboard / focus onto any DOM node you choose. **Best when you want full control over markup and styling.**
<script lang="ts">
import { createPagination } from '@kumiki/headless/pagination';
const ctl = createPagination({});
</script>
<div {@attach ctl.root}>
<!-- your markup -->
</div>Compound components (<Root> / <Trigger> / …). Markup is fixed; styling is not. Same trade-off as a typical headless UI library.
pnpm add @kumiki/components<Pagination.Root page={p} pageCount={pages} onPageChange={(n) => (p = n)}>
<Pagination.Prev />
<Pagination.PageList>
{#snippet item({ page, isCurrent, isEllipsis })}
{#if isEllipsis}
<Pagination.Ellipsis />
{:else}
<Pagination.PageItem {page}>{page}</Pagination.PageItem>
{/if}
{/snippet}
</Pagination.PageList>
<Pagination.Next />
</Pagination.Root><Pagination.Root
page={p}
pageCount={pages}
asLinks={{ href: (n) => `?p=${n}` }}
>
<!-- … -->
</Pagination.Root>Styled, copy-paste presets (preview). Run pnpm kumiki add to drop the source into your project, then edit freely.
Live preview…
pnpm add @kumiki/atelier<script lang="ts">
import { Tailwind as Pagination } from '@kumiki/atelier/pagination';
let page = $state(1);
</script>
<Pagination.Root {page} pageCount={20} onPageChange={(p) => (page = p)}>
<Pagination.Prev>‹</Pagination.Prev>
<Pagination.PageList>
{#snippet item({ page: n, isCurrent, isEllipsis })}
{#if isEllipsis}
<Pagination.Ellipsis />
{:else}
<Pagination.PageItem page={n} data-current={isCurrent ? '' : undefined}>
{n}
</Pagination.PageItem>
{/if}
{/snippet}
</Pagination.PageList>
<Pagination.Next>›</Pagination.Next>
</Pagination.Root>/ accessibility
axe-core — run on every PR (LTR + RTL × every documented state).
No component-specific keymap. Inherits standard browser focus / activation behaviour.