Skip to content
Glint UI

Pagination

A pager whose window is a fixed handful of slots, so a 200-page set draws what a 20-page one does.

Usage

import { Pagination } from "@glint/components/pagination.slint";
import { Tokens } from "@glint/theme/tokens.slint";
export component AppWindow inherits Window {
width: 520px;
height: 140px;
background: Tokens.color-background;
in-out property <int> page: 0;
VerticalLayout {
padding: 24px;
alignment: center;
HorizontalLayout {
alignment: center;
Pagination {
accessible-label: "Search results";
total: 8;
current <=> root.page;
changed(page) => { debug("load page", page); }
}
}
}
}

total is how many pages there are, counting from one. current is which one is showing, counting from zero — the index you would use against an array, not the number drawn on the button. It is two-way, so a pager can be driven from outside as well as clicked, and changed fires with the new index once a step or a number moves it.

The pager draws nothing itself but the controls. Loading the page is yours: the component reports where the reader went and stops there.

Examples

The window

A set too long to list windows itself. The pager keeps the first page, the last page, the sibling-count pages either side of the current one, and an ellipsis standing for each run in between — so the number of slots is fixed and a 200-page set draws the same handful of buttons a 20-page one does. Below the window size the set is drawn whole, because an ellipsis standing for one page saves nothing.

The ellipsis is not a control: it goes nowhere, so it takes no tab stop and leaves no node in the accessibility tree.

How many siblings

sibling-count is how many pages are drawn either side of the current one, and it is what the window is measured from: the window is both ends, both ellipses and the current page with its siblings. Raising it widens the pager everywhere, not only in the middle.

Taking a section away

show-numbers and show-steps each remove one half of the pager. Numbers alone are the simple pager; steps alone are the icons-only pair a data table wears under its rows. A step with nowhere to go dims, refuses the click and leaves the tab order, which is Button’s own disabled doing the work.

Naming the steps

The two steps are icon-only buttons, so their names are strings the component ships and a call site overrides — previous-label and next-label, both @tr(…) by default. The page numbers name themselves from their own position.

API Reference

Properties

PropertyTypeDefaultDescription
totalin int1Total number of pages (1-based count).
currentin-out int0Two-way; the active page (0-indexed internally).
previous-labelin string@tr("Previous page")Name of the icon-only step to the previous page; override to translate.
next-labelin string@tr("Next page")Name of the icon-only step to the next page; override to translate.
sibling-countin int1Pages drawn either side of the current one once the set is windowed.
show-numbersin booltrueDraw the page numbers. Off leaves the steps alone — the icons-only pager.
show-stepsin booltrueDraw the previous / next steps. Off leaves the numbers alone — the simple pager.

Callbacks

CallbackDescription
changed(int)Fired with the new page index on click.

Accessibility

  • A navigation landmark. The pager carries accessible-role: navigation and publishes accessible-item-count as total. Naming it is the call site’s — set accessible-label, so a page with a pager over its table and another under it tells the two apart.
  • Every destination is a named button. A page number announces itself Page 4, carries its index and reports whether it is the current page (accessible-item-selected), so a screen reader says where the reader is without the visual highlight.
  • The steps carry their own names and their enabled state. Previous and Next are icon-only, so previous-label and next-label are what they are announced by; a step with nowhere to go reports itself unavailable rather than disappearing.
  • The ellipsis is not announced. It stands for a run that was elided and goes nowhere, so it is not a control and leaves no node. What tells a reader where in the range they are is the landmark’s item count and each button’s own index.
  • One tab stop per destination. The pager is a set of independent destinations rather than one control with a selection inside it, so every live button in it is its own stop and Enter or Space activates the focused one. That is deliberately not the single roving stop Tabs and NavigationMenu use: a roving stop belongs to one control whose arrows move a selection inside it.