Skip to content
View as Markdown

Navigation

Pagination

Navigate through pages of content with real, addressable links, composed from parts on top of Button.

Import

TSX
import { Pagination } from "@loamui/core";

Usage

Every example has a CSS tab. That’s the real, complete stylesheet for the component: plain, static CSS, with nothing running in the browser.

Basic usage

Pagination.Pages renders Previous, the numbered window around the active page with its ellipses, and Next, from page and count. Every page has an href; intercept onNavigate only when a client router needs it.

With edges

First and last links are your own Items around Pages: a Pagination.Link is a Button rendered as a link, disabled when the destination is the current page. Ellipsis gaps keep the control compact across 20 pages.

Guidance

When to use it

  • For long result sets (search results, tables, archives) where users need to know where they are in the set and jump to a position.
  • When users may want to return to a specific point: numbered pages give every position a stable address, which continuous scrolling cannot.

When not to

  • For short lists: if everything fits on one or two pages, show it all; a pager over a handful of items adds clicks without adding orientation.
  • For feeds built for continuous browsing where position never matters: a 'load more' control fits that reading pattern better than page numbers nobody will cite.

Accessibility

  • The pager is a <nav aria-label="Pagination"> (labels.navigation replaces the name) wrapping a list, so assistive technology exposes it as a navigation landmark with a known number of items.
  • The active page carries aria-current="page", and the stylesheet keys off that same attribute, so the state is declared once; the position is announced, and colour is not the only visual signal.
  • Every available destination is a real <a href> with an explicit aria-label ("Previous page", "Page 7"); labels on Pages replaces the words. Users can copy, bookmark or open a page in a new tab.
  • Ellipsis separators are aria-hidden: they are visual shorthand for the gap, not stops in the reading order.
  • Previous and Next carry rel="prev" and rel="next". Unavailable directions are visual placeholders hidden from assistive technology, so they are not inert tab stops.

How it works

Show more per page before adding more pages

Deep pagination is a poor way to find anything: nobody browses to page 37 of 120. Before reaching for a longer pager, raise the page size or improve search and filtering so users land near what they want. Pagination is for orienting within a set, not a substitute for findability.

Previous and Next stay put

Sequential movement is what pagination is for, so Pagination.Pages always renders Previous and Next and they keep their visual space. At the first and last page the unavailable direction becomes a disabled Link: an aria-hidden placeholder with no href. The layout stays stable without adding an inert stop to the keyboard or accessibility order.

The ends are always visible

The page list always includes page 1 and the last page, with aria-hidden ellipses standing in for the gaps and sibling pages shown around the active one. Users can therefore read the size of the whole set and reach either end in one click from anywhere. First and last links are a composition: two Items of your own around Pages.

The URL is the source of truth

getHref gives every destination a real URL, so page 4 is linkable, survives reloads and supports the back button before JavaScript runs. With a client router, pass its link through Link's render, or intercept onNavigate, prevent the browser navigation and update the route there. The href remains the fallback and the destination users can copy or open in a new tab.

Parts

Pagination.Root

The <nav> landmark; native <nav> props are forwarded.

PropTypeDefaultDescription
labels{ navigation?: string }{ navigation: "Pagination" }The landmark's accessible name.

Pagination.List

The <ul> of items; native <ul> props are forwarded.

Pagination.Item

One <li>, holding a Link or your own content; native <li> props are forwarded.

Pagination.Ellipsis

An aria-hidden <li> standing in for a gap; children replace the default … glyph.

Pagination.Pages

The convenience: Previous, the numbered window with ellipses, and Next, rendered from the parts. Belongs inside Pagination.List; edge links are your own Items around it.

PropTypeDefaultDescription
pagenumber—The active page (1-based).
countnumber—Total number of pages.
siblingsnumber1Number of sibling pages shown on each side of the active page.
getHref(page: number) => string—Build the destination URL for each page (required).
onNavigate(page: number, event: MouseEvent<HTMLAnchorElement>) => void—Optionally intercept link activation for a client router.
labels{ previous?: string; next?: string; page?: (n: number) => string }{ previous: "Previous page", next: "Next page", page: (n) => "Page n" }The words the links speak: previous ("Previous page"), next ("Next page") and page(n) ("Page 7").