Skip to content
SuperCoach

Components · Navigation

Pagination

Beta

Moves through long lists, such as invoices.

Showing invoices 21–40 of 132

When to use

  • Under long lists the coach scans and comes back to: invoices, payment history, check-in history.
  • When a position in the list matters: "page 3 of the invoices" can be shared, bookmarked and returned to.
  • Under a Table or data table, with a count of what is showing: "Showing 21–40 of 132".

When not to use

  • For short lists that fit on one or two screens: show everything.
  • For feeds read top to bottom once, such as a message thread or activity: use a "Load more" button or load as the coach scrolls.
  • To move between steps of a task: use a stepper with Back and Next buttons.
  • For carousels of photos: use a carousel with its own previous and next controls.

Anatomy

  1. 1. Pagination: a nav landmark around a list
  2. 2. Previous: a chevron and a label; the label hides below sm
  3. 3. Page link: a ghost button
  4. 4. Current page: an outline button, aria-current="page"
  5. 5. Ellipsis: pages left out, hidden from screen readers
  6. 6. Next: a label and a chevron

Variants

VariantUse for
NumberedLong lists on desktop, where jumping to a page helps. Show the first and last page and the pages next to the current one, with an ellipsis for the gaps.
Previous and nextMobile, or short lists where page numbers add little. Show "Page 1 of 7" between the buttons.

States

StateWhat changesToken
Page link, restNo fillghost button variant
HoverLight fillhover:bg-accent, hover:text-accent-foreground
Current pageBorder and background, aria-current="page"outline button variant: border, bg-background, shadow-xs
Focus-visibleRingring-ring/50, 3px
Disabled (Previous on page 1, Next on the last page)Half opacity, no pointer events, no href, aria-disabled="true"opacity-(--opacity-disabled)

The first preview starts on page 2. Go to page 1 to see Previous disabled. PaginationLink is an a, so it has no disabled attribute: leave out href, add aria-disabled="true", and add the disabled classes yourself, as the examples do.

Usage guidelines

  • Always show where the coach is: the current page, and the count of results above or beside the pagination.
  • Keep Previous and Next in the same place on every page. Disable them at the ends; don't hide them, or the layout jumps.
  • Show at most 7 page slots, including ellipses, so the control doesn't wrap.
  • Put the page in the URL (?page=3) so the browser's Back button and shared links work. Each page link has a real href.
  • After changing page, keep focus on the pagination and update the count, so keyboard users don't lose their place.
Do.Previous, a few page numbers with the current one marked, Next.
Don't.Every page number, no Previous or Next, and no current page. The coach can't tell where they are.

Content guidelines

  • The count says what the items are: "Showing 21–40 of 132 invoices", or "Showing invoices 21–40 of 132". Use an en dash in ranges.
  • "Previous" and "Next", not "Prev", arrows alone or "Older". The labels come from lib/ui-labels, so Arabic screens get "السابق" and "التالي".
  • Numbers use tabular figures (tabular-nums) so the control doesn't shift as pages change.
  • Arabic: "عرض الفواتير 21–40 من 132". Western digits.

Accessibility

KeyDoes
TabMoves through Previous, each page link and Next. Disabled ends and the ellipsis are skipped
EnterOpens the focused page
  • A nav landmark labelled "Pagination" ("التنقل بين الصفحات" in Arabic), around a list of links.
  • The current page has aria-current="page": "2, current page, link". Other pages read as "3, link".
  • Previous and Next are labelled "Go to previous page" and "Go to next page". The visible words "Previous" and "Next" are part of those names, so voice control ("click Next") still works.
  • The ellipsis is aria-hidden. Its visually hidden "More pages" text is hidden with it, so it is not announced at all, which is fine: the page numbers on each side tell the story.
  • Put the "Showing …" count in a role="status" element, as the example does, so the new range is announced after a page change.
  • Page links are 36px square, above the 24px minimum target size.

RTL

The list runs from right to left: Previous is on the right and Next on the left. The chevrons mirror (rtl:-scale-x-100), so "previous" always points back toward the start. Page numbers keep their own order within the list (1, 2, 3 from right to left) and are not reversed as text.

Tokens used

Pagination has no classes of its own beyond layout. Page links are Button styles: ghost for pages and outline for the current page, so they read Button's tokens. The generated table is left out here because components/ui/pagination.tsx itself contains no token classes.

Props

<Pagination>

Also takes every prop of <nav>

No props of its own.

<PaginationContent>

Also takes every prop of <ul>

No props of its own.

<PaginationItem>

Also takes every prop of <li>

No props of its own.

Also takes every prop of <a>

PaginationLink props
PropTypeDefault
isActive?boolean—
size?from <Button>"icon"

<PaginationPrevious>

Also takes every prop of <PaginationLink>

No props of its own.

<PaginationNext>

Also takes every prop of <PaginationLink>

No props of its own.

<PaginationEllipsis>

Also takes every prop of <span>

No props of its own.

PaginationLink also takes isActive (boolean, marks the current page) and size (a Button size, "icon" by default). They are declared in a type alias that the props generator doesn't read yet.

Replaces in coach-admin

From the read-only audit of coach-admin: 5 style values, 5 uses.

coach-admin has no styled pagination. Long lists use a "Load more" button (.load-more-btn), which stays right for feeds; tables and invoice lists that need a position should move to Pagination. src/views/Base/Paginations is a CoreUI demo page (DECISIONS #10).

Classes and selectors

  • .load-more-btn3
  • .trainees-list__load-more-sr1
  • .load-more-btn__icon1

Table, Data table, Button, Breadcrumb.