Sakuga Back to Sakuga
Theme
Sound
Jump to a component

Core · Navigation

Pagination

Pagination reads a long list a page at a time: what this page holds, then previous, the page numbers and next. A list of one page shows none.

@anicanon/sakuga/uiv1.0Used onWeb · iOS · Android

Live, from @anicanon/sakuga 2.0.0

Sakuga for iOS and Android is coming

iOS

Coming soon

Pagination for iOS is in the roughs. The tokens it will read are the ones on this page, the same on every platform.

Android

Coming soon

Pagination for Android is in the roughs. The tokens it will read are the ones on this page, the same on every platform.

Use it for
Reading a long list a page at a time, under the list it pages: productions at 24 a page, counted as "1–24 of 31 shorts".
Not for
  • Where a person is in a flow they step throughStepper
  • A shelf that leads to everything on itSectionHeader
  • The pages of a manga issue in the editorIssueStrip

Guidelines

  • Pass page, pages and, when the total is known, total, pageSize and noun: the count reads "1–24 of 31 shorts".
  • Every number carries the page language's thousands separator (<html lang>, English when it has none): "1–25 of 2,481 people", and "2.481" on a Portuguese page. The page numbers do too, spoken and shown.
  • Lists of productions page at 24, as the product's clips list does; search and filters sit above the list and send you back to page 1.
  • Far pages fold into an ellipsis around the current one: 1 … 4 5 6 … 12.
  • hrefs gives each page an address; without it the pages are buttons that call onChange with the page.
  • The current page's fill slides to the new page on motion-base; numbers sink on press.
  • With sound on, going to another page plays the choose sound, from a number or an arrow (README · Sound).
  • Put it under the list it pages, across the list's full width. One per list.
  • Sliding across the page numbers moves the pill with the pointer; let go on a number to go to that page.
PaginationExample.jsxReact
import { useState } from 'react';
import { Pagination } from '@anicanon/sakuga/ui';

export default function PaginationExample() {
  const [page, setPage] = useState(1);
  const [page2, setPage2] = useState(5);
  return (
    <>
      <Pagination
        page={page}
        pages={2}
        total={31}
        pageSize={24}
        noun="shorts"
        label="Pages of shorts"
        onChange={setPage}
      />
      <Pagination
        page={page2}
        pages={12}
        total={281}
        pageSize={24}
        noun="pictures"
        label="Pages of pictures"
        onChange={setPage2}
      />
    </>
  );
}

PropsPaginationProps

pagerequired
number
pagesrequired
number
total
number
With total, the count reads "1–24 of 31 shorts"; without, "Page 1 of 2".
pageSize
number
noun
string
label
stringDefault 'Pages'
hrefs
string[]
One address per page, in order.
onChange
(page: number) => void
Without hrefs: called with the page to show.
className
string
PaginationExample.swiftiOS · coming soon
PaginationExample.ktAndroid · coming soon

Each token reads a role, and the role lands on a value in each theme. Change the role and every component that reads it follows.

Space and shape

pagination-gap
gap-xl
16px
pagination-padding-top
inset-lg
16px
pagination-edge-top-width
its own value
1px
pagination-nav-gap
gap-2xs
2px
pagination-nav-icon-button-disabled-opacity
opacity-disabled
0.35
pagination-n-min-width
its own value
36px
pagination-n-height
its own value
36px
pagination-n-padding-x
inset-sm
8px
pagination-n-radius
radius-full
9999px
pagination-n-active-scale
scale-press-sm
.94
pagination-gap-min-width
its own value
24px
pagination-nav-glide-radius
radius-full
9999px

Type

pagination-count-font
text-caption
500 13px/18px "Funnel Sans", system-ui, -apple-system, "Segoe UI", sans-serif
pagination-n-font
text-label
600 14px/20px "Funnel Sans", system-ui, -apple-system, "Segoe UI", sans-serif
pagination-gap-font
text-label
600 14px/20px "Funnel Sans", system-ui, -apple-system, "Segoe UI", sans-serif

Motion

pagination-n-duration
motion-fast
160ms
pagination-n-easing
ease-standard
cubic-bezier(0.2, 0, 0, 1)
pagination-n-active-duration
motion-instant
100ms

Checked automatically with axe-core 4.11.4 against WCAG 2.2 A and AA, on the live preview above, in light and dark, on 26 October 2026.

Result
No issues found, in light or in dark.
By design
A navigation region named by label (default "Pages"): the count reads as text, then Tab moves through "Previous page", each "Page 3" (the current one marked "current page") and "Next page", which are disabled at the ends: an arrow that turns off under focus hands focus to the current page. The ellipsis is hidden. Sliding is for the pointer; each page is still its own link or button.
Not tested
The automated check doesn't test keyboard use, focus order or what a screen reader says. The lines above are the design system's own account of them.