Pagination
Navigate between pages of content.
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.
Runs in a view's render: self is the view holding this example's state and cx is its Context<Self>.
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_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>.
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()])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>.
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"))
}))Runs in a view's render: self is the view holding this example's state and cx is its Context<Self>.
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()])Runs in a view's render: self is the view holding this example's state and cx is its Context<Self>.
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-links", page, 8)
.disabled_keys([0, 5, 9])
.on_change(cx.listener(|this, p: &usize, _, cx| {
this.pagination_page = *p;
cx.notify();
}))
.into_any_element()])Runs in a view's render: self is the view holding this example's state and cx is its Context<Self>.
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()])Runs in a view's render: self is the view holding this example's state and cx is its Context<Self>.
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).
Runs in a view's render: self is the view holding this example's state and cx is its Context<Self>.
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()])Runs in a view's render: self is the view holding this example's state and cx is its Context<Self>.
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()])`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>.
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(),
])`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>.
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(),
])Runs in a view's render: self is the view holding this example's state and cx is its Context<Self>.
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.
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 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
| Method | Values | Description |
|---|---|---|
size(Size) | Size::Sm | Size::Md | Size::Lg | Size of the pagination items. |
// 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
| Builder | Values | Default | Description |
|---|---|---|---|
size( | Size:: | Size:: | Size of the pagination items. |
new(Partial | AnyElement | — | Pagination parts; the GPUI port generates the compound structure. |
summary(Partial | AnyElement | — | Summary content such as a visible item range. |
link( | true | | false | Marks the current page and is handed to the link render closure. |
disabled_keys( | true | | false | Disables one page link by page number. |
on_change(Partial | Fn( | — | Reports a normalized pointer or keyboard press with its page number. |
previous_icon( | AnyElement | Default chevron SVG | Custom icon replacing the previous chevron. |
next_icon( | AnyElement | Default chevron SVG | Custom icon replacing the next chevron. |
Not ported9 HeroUI entries not ported
| HeroUI v3 | Why it is not ported |
|---|---|
Pagination.className | |
Pagination.Summary.className | For the summary. |
Pagination.Content.className | For the item container. |
Pagination.Item.className | For one item wrapper. |
Pagination.Link.className | For a link. |
Pagination.Previous / Pagination.Next.className | For a navigation button. |
Pagination.PreviousIcon.className | For the previous icon. |
Pagination.NextIcon.className | For the next icon. |
Pagination.Ellipsis.className | For the ellipsis. |
Parts
| Part | Description |
|---|---|
PaginationPartial | Root page-navigation container. |
PaginationPartial | Optional summary before the links. |
PaginationPartial | Container for navigation items. |
PaginationPartial | Implicit wrapper around one item. |
Pagination | Focusable page-number button. |
Pagination | Button targeting the previous page. |
Pagination | Replaceable previous-page icon. |
Pagination | Button targeting the next page. |
Pagination | Replaceable next-page icon. |
Pagination | Non-interactive omitted-page marker. |
States
| State | Builder | Description |
|---|---|---|
Active page | link(page, active) | Current page with tertiary-button fill and AccessKit aria-current=page semantics. |
Hovered | hover(default.hover()) | Enabled link or nav-button hover fill. |
Focused | tab_stop_handle | Keyboard focus ring. |
DisabledPartial | is_disabled | No press or tab stop, with disabled opacity. |
PressedPartial | anim::pressed | Size-specific scale and default-hover fill. |