Skip to content
v1.0.3

Pagination

Page navigation for tables and lists. Previous/next arrows, numbered pages that collapse to "…" around the current page, and an optional "1–20 of 482" summary. It's controlled — you track the page and update it on change.

bash
jlds add pagination

Usage

html
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/jarooda/jlds@main/registry/css/index.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/jarooda/jlds@main/registry/css/pagination.css">

<nav class="jl-pagination" aria-label="Pagination">
  <div class="jl-pagination__list">
    <button class="jl-page jl-page--arrow" aria-label="Previous page">‹</button>
    <button class="jl-page" aria-label="Page 1">1</button>
    <button class="jl-page" aria-current="page" aria-label="Page 2">2</button>
    <button class="jl-page" aria-label="Page 3">3</button>
    <button class="jl-page jl-page--arrow" aria-label="Next page">›</button>
  </div>
</nav>
vue
<script setup lang="ts">
import { ref } from "vue"
import { Pagination } from "@/components/ui/pagination"

const page = ref(2)
</script>

<template>
  <Pagination v-model:page="page" :page-count="10" />
</template>
tsx
import { useState } from "react"
import { Pagination } from "@/components/ui/pagination"

const [page, setPage] = useState(2)

<Pagination page={page} pageCount={10} onChange={setPage} />

Collapsed (many pages)

With many pages, the middle collapses to "…" — siblingCount controls how many neighbors stay visible around the current page.

html
<nav class="jl-pagination" aria-label="Pagination">
  <div class="jl-pagination__list">
    <button class="jl-page jl-page--arrow" aria-label="Previous page">‹</button>
    <button class="jl-page" aria-label="Page 1">1</button>
    <span class="jl-page jl-page--ellipsis" aria-hidden="true">…</span>
    <button class="jl-page" aria-label="Page 5">5</button>
    <button class="jl-page" aria-current="page" aria-label="Page 6">6</button>
    <button class="jl-page" aria-label="Page 7">7</button>
    <span class="jl-page jl-page--ellipsis" aria-hidden="true">…</span>
    <button class="jl-page" aria-label="Page 20">20</button>
    <button class="jl-page jl-page--arrow" aria-label="Next page">›</button>
  </div>
</nav>
vue
<template>
  <Pagination v-model:page="page" :page-count="20" :sibling-count="1" />
</template>
tsx
<Pagination page={page} pageCount={20} siblingCount={1} onChange={setPage} />

With summary

Pass total, pageSize, and showSummary for the "1–20 of 482" readout on the left.

html
<nav class="jl-pagination" aria-label="Pagination">
  <div class="jl-pagination__summary"><b>1–20</b> of <b>482</b></div>
  <div class="jl-pagination__spacer"></div>
  <div class="jl-pagination__list"><!-- page buttons --></div>
</nav>
vue
<template>
  <Pagination
    v-model:page="page"
    :page-count="25"
    :total="482"
    :page-size="20"
    show-summary
  />
</template>
tsx
<Pagination
  page={page}
  pageCount={25}
  total={482}
  pageSize={20}
  showSummary
  onChange={setPage}
/>

Props

React

Pagination extends React.HTMLAttributes<HTMLElement> (minus onChange).

PropTypeDefaultDescription
pagenumber1Current page (1-based)
pageCountnumberTotal number of pages (required)
totalnumberRecord count — for the summary
pageSizenumberRecords per page — for the summary
siblingCountnumber1Pages shown each side of current before "…"
showSummarybooleanfalseShow the "1–20 of 482" summary
onChange(page: number) => voidFires with the next page

Vue

Same props. Supports v-model:page, and also emits a change event with the next page.

CSS classes (HTML)

ClassPurpose
.jl-paginationWrapper (nav)
.jl-pagination__summaryThe "1–20 of 482" readout
.jl-pagination__spacerPushes the page list to the right
.jl-pagination__listThe control group
.jl-pageA page button (use aria-current="page" for the active one)
.jl-page--arrowPrevious/next arrow buttons
.jl-page--ellipsisThe "…" gap