Pagination

Pagination is the page-navigation control for long result sets.
Use it when the product already has a concept of discrete pages, such as search results, logs, invoices, or admin tables. Pagination solves a different problem than infinite scroll. It trades continuous browsing for clear location, predictable back-and-forth movement, and stable URLs or queries.

Example

use fission::prelude::*;
use std::sync::Arc;

let widget: Widget = Pagination {
    current_page: view.state().page,
    total_pages: view.state().total_pages,
    on_change: Some(Arc::new(move |page| ActionEnvelope {
        id: set_page_id,
        payload: serde_json::to_vec(&SetPage(page)).unwrap(),
    })),
}
.into();
The reducer usually stores the current page and then refreshes the data set through a selector or follow-up effect.

Field table

Field
Type
Meaning
Notes / default behavior
current_page
usize
Currently selected page number.
The checked-in widget behaves as a 1-based pager.
total_pages
usize
Total number of available pages.
Provide a value of at least 1 for normal use.
on_change
Option<Arc<dyn Fn(usize) -> ActionEnvelope + Send + Sync>>
Closure that builds the action for a chosen page.
Called for previous, next, and numbered page buttons.

State ownership and behavior

The widget does not calculate paging for you. It only renders page controls from the current state. The reducer still decides what page data to load and how page numbers map to queries or offsets.
The checked-in implementation shows a sliding window of page buttons with ellipses when needed. Previous and next buttons disable themselves at the ends of the range.

Specific advice

Use pagination only if the product already benefits from discrete pages. If users mostly scan continuously through a stream, pagination can feel like unnecessary friction.

Production checklist

For Pagination, review the fields that change behavior before treating the widget as finished: current_page, total_pages, on_change. The goal is to make the product rule visible in state and actions, not hidden inside ad-hoc construction code.
Bind on_change to explicit reducer actions and test that the reducer handles unavailable, duplicate, or invalid input safely.
Check the semantics tree for the user-facing label or role that makes this widget understandable without relying only on pixels.
Add at least one component or harness test that confirms the visible text, semantic role, action dispatch, and layout constraint that matter for this widget in context.
If a screen starts repeating the same Pagination setup, extract a named component around this widget. That keeps the reference API small while making product code easier to read and safer for generated code to copy.
DataTable, Scroll, LazyColumn, and EmptyState.
Fission
A cross-platform, GPU-accelerated user interface framework for Rust. MIT licensed.
Copyright (c) 2026 Fission
Ready to use today. Widget APIs are expected to remain stable; some runtime and shell APIs may change before 1.0.0.
Fission 0.7.0