Pagination

A controlled pager for ordered result sets. First, last and the current page plus or minus one are always reachable, so the control holds its width at any page count.

import from ~/components/ui/pagination

The window

page 7 of 12

First, last, and the current page plus or minus one are always shown. Everything else collapses, so the control keeps its width whatever the page count is.

Edges

first page

Previous is disabled at page 1. The control never disappears, so the pager does not jump around between pages.

last page

Next is disabled at the last page. The current page carries aria-current, not just the fill.

Truncation

two ellipses

A page in the middle of a long range truncates on both sides.

no ellipsis over a single page

Page 3 of 6 would leave page 5 alone behind an ellipsis. The component prints the number instead, since the ellipsis takes the same width and makes the page unreachable.

short range

Five pages fit whole. Truncation only starts when there is something to hide.

a single page

One page still renders, with both arrows disabled. Consider hiding the pager entirely at this point.

In context

Showing 61 to 70 of 118 endeavors

under a result list

The pager sits below the results, aligned to the end of the row, with the count on the left.

Rules

Do

Use it for ordered result sets where a reader wants to jump to a known page.
Keep it controlled: pass page and pageCount, and move the page in onPageChange.
Say what is being paged near it, for example "61 to 70 of 118". A pager alone gives no scale.
Reflect the page in the URL so a reader can link to, reload, or share the page they are on.

Don't

Do not use it for a feed with no end. Load-more or infinite scroll fits an unbounded list.
Do not hand-build a page window at the call site. computePages already owns that logic.
Do not hide previous and next at the ends. Disabled arrows keep the control from shifting.
Do not put a second pager above the list as well. One pager per result set.