Skip to content
PorabuildHeroGPUI component library
v0.14.0 · Apache-2.0

Navigation

Pagination

Navigate between pages of content.

Rust
use herogpui::components::pagination::Pagination;

Pagination on docs.rsSource at v0.14.0

Usage

Showing Usage, live: HeroGPUI compiled to WebAssembly. The canvas has no accessibility tree; each example's description and code below carry the same information.

Usage

Runs in a view's render: self is the view holding this example's state and cx is its Context<Self>.

Rust
use herogpui::prelude::Pagination;
use herogpui::gpui::prelude::*;
use herogpui::gpui::px;
use herogpui::gpui;

let page = self.pagination_page;

gpui::div()
    .flex()
    .flex_col()
    .items_start()
    .justify_center()
    .gap(px(12.))
    .children(vec![Pagination::new("pagination-main", page, 10)
        .full_width(true)
        .on_change(cx.listener(|this, p: &usize, _, cx| {
            this.pagination_page = *p;
            cx.notify();
        }))
        .into_any_element()])

Hover Colour

`hover_bg` names the fill enabled links and nav buttons take while hovered or pressed; the per-size press scale is unchanged. Runs in a view's render: self is the view holding this example's state and cx is its Context<Self>.

Rust
use herogpui::prelude::{ActiveTheme, Pagination};
use herogpui::gpui::prelude::*;
use herogpui::gpui::px;
use herogpui::gpui;

let page = self.pagination_page;

gpui::div()
    .flex()
    .flex_col()
    .items_start()
    .justify_center()
    .gap(px(12.))
    .children(vec![Pagination::new("pagination-hover-bg", page, 6)
        .hover_bg(cx.colors().accent.soft_hover())
        .on_change(cx.listener(|this, p: &usize, _, cx| {
            this.pagination_page = *p;
            cx.notify();
        }))
        .into_any_element()])

Sizes

Summary and link typography scale together and keep their line height in larger text containers. Runs in a view's render: self is the view holding this example's state and cx is its Context<Self>.

Rust
use herogpui::prelude::{Pagination, Size};
use herogpui::gpui::prelude::*;
use herogpui::gpui::px;
use herogpui::gpui;

let page = self.pagination_page;

gpui::div()
    .flex()
    .flex_col()
    .items_start()
    .justify_center()
    .gap(px(12.))
    .children(Size::ALL
        .iter()
        .map(|sz| {
            Pagination::new(format!("pagination-{sz:?}"), page, 8).size(*sz)
                .summary(format!("Page {page} of 8"))
        }))

Disabled

Runs in a view's render: self is the view holding this example's state and cx is its Context<Self>.

Rust
use herogpui::prelude::Pagination;
use herogpui::gpui::prelude::*;
use herogpui::gpui::px;
use herogpui::gpui;

let page = self.pagination_page;

gpui::div()
    .flex()
    .flex_col()
    .items_start()
    .justify_center()
    .gap(px(12.))
    .children(vec![Pagination::new("pagination-disabled", page, 8)
        .is_disabled(true)
        .into_any_element()])
Rust

Simple (Previous / Next)

Runs in a view's render: self is the view holding this example's state and cx is its Context<Self>.

Rust
use herogpui::prelude::{Button, Pagination, Variant};
use herogpui::gpui::prelude::*;
use herogpui::gpui::px;
use herogpui::gpui;

let page = self.pagination_page;

gpui::div()
    .flex()
    .flex_col()
    .items_start()
    .justify_center()
    .gap(px(12.))
    .children(vec![gpui::div()
                       .flex()
                       .flex_wrap()
                       .items_center()
                       .justify_center()
                       .gap(px(12.))
                       .children(vec![
                               Button::new("pagination-prev")
                                   .label("Previous")
                                   .variant(Variant::Tertiary)
                                   .is_disabled(page <= 1)
                                   .on_press(cx.listener(|this, _, _, cx| {
                                       this.pagination_page =
                                           this.pagination_page.saturating_sub(1).max(1);
                                       cx.notify();
                                   }))
                                   .into_any_element(),
                               gpui::div()
                                   .text_size(px(13.5))
                                   .child(format!("Page {page} of 8"))
                                   .into_any_element(),
                               Button::new("pagination-next")
                                   .label("Next")
                                   .variant(Variant::Tertiary)
                                   .is_disabled(page >= 8)
                                   .on_press(cx.listener(|this, _, _, cx| {
                                       this.pagination_page = (this.pagination_page + 1).min(8);
                                       cx.notify();
                                   }))
                                   .into_any_element(),
                           ])
                       .into_any_element()])

Controlled

Runs in a view's render: self is the view holding this example's state and cx is its Context<Self>.

Rust
use herogpui::prelude::{ActiveTheme, Pagination};
use herogpui::gpui::prelude::*;
use herogpui::gpui::{App, px};
use herogpui::gpui;

let page = self.pagination_page;

gpui::div()
    .flex()
    .flex_col()
    .items_start()
    .justify_center()
    .gap(px(12.))
    .children(vec![
        Pagination::new("pagination-controlled", page, 8)
            .on_change(cx.listener(|this, p: &usize, _, cx| {
                this.pagination_page = *p;
                cx.notify();
            }))
            .into_any_element(),
        para(&format!("Page {page}"), cx),
    ])

Also calls para (included when you copy).

With Ellipsis

Runs in a view's render: self is the view holding this example's state and cx is its Context<Self>.

Rust
use herogpui::prelude::Pagination;
use herogpui::gpui::prelude::*;
use herogpui::gpui::px;
use herogpui::gpui;

let page = self.pagination_page;

gpui::div()
    .flex()
    .flex_col()
    .items_start()
    .justify_center()
    .gap(px(12.))
    .children(vec![Pagination::new("pagination-ellipsis", page, 24)
        .on_change(cx.listener(|this, p: &usize, _, cx| {
            this.pagination_page = *p;
            cx.notify();
        }))
        .into_any_element()])

With Summary

Runs in a view's render: self is the view holding this example's state and cx is its Context<Self>.

Rust
use herogpui::prelude::Pagination;
use herogpui::gpui::prelude::*;
use herogpui::gpui::px;
use herogpui::gpui;

let page = self.pagination_page;

gpui::div()
    .flex()
    .flex_col()
    .items_start()
    .justify_center()
    .gap(px(12.))
    .children(vec![Pagination::new("pagination-summary", page, 12)
        .summary(format!(
            "Showing {}-{} of 120 items",
            (page.saturating_sub(1)) * 10 + 1,
            (page * 10).min(120)
        ))
        .on_change(cx.listener(|this, p: &usize, _, cx| {
            this.pagination_page = *p;
            cx.notify();
        }))
        .into_any_element()])

Render Props

`link` receives each page number and `isActive`, so custom page content does not have to re-derive the current page. Runs in a view's render: self is the view holding this example's state and cx is its Context<Self>.

Rust
use herogpui::prelude::Pagination;
use herogpui::gpui::prelude::*;
use herogpui::gpui::px;
use herogpui::gpui;

let page = self.pagination_page;

gpui::div()
    .flex()
    .flex_col()
    .items_start()
    .justify_center()
    .gap(px(12.))
    .children(vec![
        Pagination::new("pagination-render-props", page, 5)
            .link(|page, is_active| {
                gpui::div()
                    .child(if is_active {
                        format!("[{page}]")
                    } else {
                        page.to_string()
                    })
                    .into_any_element()
            })
            .on_change(cx.listener(|this, p: &usize, _, cx| {
                this.pagination_page = *p;
                cx.notify();
            }))
            .into_any_element(),
    ])

Custom Icons

`previous_icon` and `next_icon` replace the built-in chevrons on the composed previous and next parts. Runs in a view's render: self is the view holding this example's state and cx is its Context<Self>.

Rust
use herogpui::prelude::{ActiveTheme, Pagination, icons};
use herogpui::gpui::prelude::*;
use herogpui::gpui::px;
use herogpui::gpui;

let page = self.pagination_page;

gpui::div()
    .flex()
    .flex_col()
    .items_start()
    .justify_center()
    .gap(px(12.))
    .children(vec![
        Pagination::new("pagination-custom", page, 5)
            .previous_icon(gpui::svg()
                               .size(px(16.))
                               .path(icons::ARROW_LEFT)
                               .text_color(cx.colors().foreground)
                               .into_any_element())
            .next_icon(gpui::svg()
                           .size(px(16.))
                           .path(icons::ARROW_RIGHT)
                           .text_color(cx.colors().foreground)
                           .into_any_element())
            .on_change(cx.listener(|this, p: &usize, _, cx| {
                this.pagination_page = *p;
                cx.notify();
            }))
            .into_any_element(),
    ])

Without controls

Runs in a view's render: self is the view holding this example's state and cx is its Context<Self>.

Rust
use herogpui::prelude::Pagination;
use herogpui::gpui::prelude::*;
use herogpui::gpui::px;
use herogpui::gpui;

let page = self.pagination_page;

gpui::div()
    .flex()
    .flex_col()
    .items_start()
    .justify_center()
    .gap(px(12.))
    .children(vec![Pagination::new("pagination-plain", page, 10)
        .on_change(cx.listener(|this, p: &usize, _, cx| {
            this.pagination_page = *p;
            cx.notify();
        }))
        .into_any_element()])

Helpers used by these examples

Plain functions over the public API, defined once here and copied with each example that calls them.

para
fn para(text: &str, cx: &App) -> gpui::AnyElement {
    let colors = cx.colors();
    gpui::div()
        .text_size(px(14.5))
        .line_height(px(24.))
        .text_color(colors.foreground)
        .max_w(px(720.))
        .child(text.to_owned())
        .into_any_element()
}

Anatomy

Rust types

Pagination

Pagination is assembled from these builders. The API reference lists each one.

Customization

Shared appearance belongs on ThemeBuilder::components and .recipe("name"). Typed builders change how Pagination looks at one call site. Every builder also carries sx for placement, width and flex: it takes GPUI's own styling methods and refines them over the component's root after the theme, so an instance override wins. Behaviour builders live in the API reference below.

Styling

Pagination styling
MethodValuesDescription
size(Size)Size::Sm | Size::Md | Size::LgSize of the pagination items.
Rust
// The one slot for caller-owned low-level styling: GPUI's
// styling methods, refined over the root element last.
.sx(|el| {
    el.bg(gpui::rgba(0xffa500ff))             // background
        .text_color(gpui::rgba(0x000000ff))   // text
        .w(gpui::px(13.))                     // size
        .h(gpui::px(12.))
})

API reference

Against HeroUI v3.2.6: 16 entries ported, 13 partial, 9 not ported. Partial rows are marked in the tables; entries not ported are listed under each table with the reason.

Builders

Pagination builders
BuilderValuesDefaultDescription
size(Size)Size::Sm | Size::Md | Size::LgSize::MdSize of the pagination items.
new(id, page, total)PartialAnyElement—Pagination parts; the GPUI port generates the compound structure.
summary(text)PartialAnyElement—Summary content such as a visible item range.
link(render)true | falsefalseMarks the current page and is handed to the link render closure.
disabled_keys(keys)true | falsefalseDisables one page link by page number.
on_change(callback)PartialFn(e: ClickEvent) -> ()—Reports a normalized pointer or keyboard press with its page number.
previous_icon(icon)AnyElementDefault chevron SVGCustom icon replacing the previous chevron.
next_icon(icon)AnyElementDefault chevron SVGCustom icon replacing the next chevron.
Not ported9 HeroUI entries not ported
Pagination builders not ported
HeroUI v3Why it is not ported
Pagination.className
Pagination.Summary.classNameFor the summary.
Pagination.Content.classNameFor the item container.
Pagination.Item.classNameFor one item wrapper.
Pagination.Link.classNameFor a link.
Pagination.Previous / Pagination.Next.classNameFor a navigation button.
Pagination.PreviousIcon.classNameFor the previous icon.
Pagination.NextIcon.classNameFor the next icon.
Pagination.Ellipsis.classNameFor the ellipsis.

Parts

Pagination parts
PartDescription
PaginationPartialRoot page-navigation container.
PaginationPartialOptional summary before the links.
PaginationPartialContainer for navigation items.
PaginationPartialImplicit wrapper around one item.
PaginationFocusable page-number button.
PaginationButton targeting the previous page.
PaginationReplaceable previous-page icon.
PaginationButton targeting the next page.
PaginationReplaceable next-page icon.
PaginationNon-interactive omitted-page marker.

States

Pagination states
StateBuilderDescription
Active pagelink(page, active)Current page with tertiary-button fill and AccessKit aria-current=page semantics.
Hoveredhover(default.hover())Enabled link or nav-button hover fill.
Focusedtab_stop_handleKeyboard focus ring.
DisabledPartialis_disabledNo press or tab stop, with disabled opacity.
PressedPartialanim::pressedSize-specific scale and default-hover fill.