Pagination

The Pagination component provides page navigation with next and previous links. It displays page numbers and allows users to navigate through multiple pages of content.

Install

#Import

use gpui_kit::component::pagination::Pagination;
// Installed in ui/components. That directory is on the Slint include path, so import by file name:
import { Pagination } from "pagination.slint";
use iced::widget::{column, container, mouse_area, row, svg, text};
use iced::{Alignment, Element, Length, Task, Theme};

#Usage

#Pages

GPUINo GPUI version of this example yet.
SlintNo Slint version of this example yet.
// The compact default: icon-only step buttons, the run at page one so the
// trailing ellipsis and the last page are both in view.
let pages = Pagination::new()
    .page(app.pages_page)
    .pages(12)
    .on_change(Message::PagesPage);

By default, the pagination shows up to 5 visible page buttons. You can customize this with visible_pages():

Pagination::new("my-pagination")
    .current_page(1)
    .total_pages(50)
    .visible_pages(10)
    .on_click(|page, _, cx| {
        // Handle page change
    })
Pagination {
    pages: 12;
    page: 1;
}

#Basic Pagination

Pagination::new("my-pagination")
    .current_page(5)
    .total_pages(10)
    .on_click(|page, _, cx| {
        println!("Navigated to page: {}", page);
    })
description: "The step buttons carry their labels.";
Pagination {
    pages: 10;
    page: 5;
    compact: false;
}
// GPUI's plain `Pagination` labels its step buttons and pairs each label with
// its arrow: "‹ Previous" and "Next ›". The run stays five wide and carries
// the current page at its centre.
let basic = Pagination::new()
    .page(app.basic_page)
    .pages(10)
    .compact(false)
    .on_change(Message::BasicPage);

#Compact Style

The compact style only shows the previous and next buttons with icons, without displaying page numbers.

Use compact method to enable compact style:

Pagination::new("my-pagination")
    .compact()
    .current_page(3)
    .total_pages(10)
    .on_click(|page, _, cx| {
        // Handle page change
    })
SlintNo Slint version of this example yet.

#Different Sizes

GPUINo GPUI version of this example yet.
SlintNo Slint version of this example yet.
// One control at each of the four tiers. `xsmall` keeps the arrows at the
// control height the size gives it, so the whole row shrinks with it.
let sizes = column![
    Pagination::new()
        .page(app.xsmall_page)
        .pages(8)
        .size(ControlSize::XSmall)
        .on_change(Message::XSmallPage),
    Pagination::new()
        .page(app.medium_page)
        .pages(8)
        .size(ControlSize::Medium)
        .on_change(Message::MediumPage),
    Pagination::new()
        .page(app.large_page)
        .pages(8)
        .size(ControlSize::Large)
        .on_change(Message::LargePage),
]
.spacing(theme::SPACING_MD)
.align_x(Alignment::Start);

The Pagination supports the Sizable trait for different sizes:

use gpui_kit::component::{Sizable as _, Size};

Pagination::new("my-pagination")
    .xsmall()
    .current_page(1)
    .total_pages(10)

Pagination::new("my-pagination")
    .small()
    .current_page(1)
    .total_pages(10)

Pagination::new("my-pagination")
    .current_page(1)
    .total_pages(10) // Medium (default)

Pagination::new("my-pagination")
    .large()
    .current_page(1)
    .total_pages(10)
Pagination {
    pages: 8;
    page: 2;
    size: ControlSize.xsmall;
}
Pagination {
    pages: 8;
    page: 3;
    size: ControlSize.medium;
}
Pagination {
    pages: 8;
    page: 4;
    size: ControlSize.large;
}

#Disabled State

Pagination::new("my-pagination")
    .current_page(4)
    .total_pages(10)
    .disabled(true)
    .on_click(|_, _, _| {})
VerticalLayout {
    spacing: 12px;
    alignment: start;
    Pagination {
        pages: 5;
        page: 1;
    }
    Pagination {
        pages: 5;
        page: 5;
    }
}
// The arrow that has nowhere to go is disabled, so a first page cannot step
// back and a last page cannot step on. The page numbers stay live, which is
// the Slint component: only the arrow at the boundary is `enabled: false`.
let disabled = column![
    Pagination::new()
        .page(app.first_page)
        .pages(5)
        .on_change(Message::FirstPage),
    Pagination::new()
        .page(app.last_page)
        .pages(5)
        .on_change(Message::LastPage),
]
.spacing(theme::SPACING_MD)
.align_x(Alignment::Start);

#Handle Page Change Events

The on_click callback receives the new page number when users click on page numbers, previous, or next buttons:

Pagination::new("my-pagination")
    .current_page(current_page)
    .total_pages(total_pages)
    .on_click(|page, _, cx| {
        // Update your state with the new page
        // The page number is 1-based
    })
SlintNo Slint version of this example yet.

#With State Management

let mut current_page = 1;
let total_pages = 20;

Pagination::new("pagination")
    .current_page(current_page)
    .total_pages(total_pages)
    .on_click({
        let entity = entity.clone();
        move |page, _, cx| {
            entity.update(cx, |this, cx| {
                this.current_page = *page;
                cx.notify();
            });
        }
    })
SlintNo Slint version of this example yet.

#Large Dataset Pagination

For large datasets, use visible_pages() to show more page options:

Pagination::new("large-pagination")
    .current_page(25)
    .total_pages(100)
    .visible_pages(10)
    .on_click(|page, _, cx| {
        // Load data for the new page
    })
SlintNo Slint version of this example yet.

#API Reference

#Sizing

Implements Sizable trait:

  • xsmall() - Extra small size
  • small() - Small size
  • medium() - Medium size (default)
  • large() - Large size
  • with_size(size) - Set custom size

#Methods

  • current_page(page: usize) - Set the current page number (1-based). The value will be clamped between 1 and total_pages.
  • total_pages(pages: usize) - Set the total number of pages.
  • visible_pages(max: usize) - Set the maximum number of visible page buttons (default: 5).
  • compact() - Enable compact style (only shows prev/next buttons with icons).
  • disabled(bool) - Set the disabled state.
  • on_click(handler) - Set the handler for page change events.

#Pagination

Page controls. Mirrors GPUI Component's `Pagination`.

NameKindTypeDefaultDescription
pagein-outint1
pagesinint10
sizeinControlSizeControlSize.small
compactinbooltrueIcon-only previous and next buttons, which is how GPUI's `compact()` renders them. Setting it false labels the pair "Previous" and "Next", which is what GPUI's plain `Pagination` shows.
changedcallback(page: int)