Biji UI

Pagination

A headless pagination state container. Derives page count, prev/next availability, and item offset from controlled page, page_size, and total signals.

Installation

biji-ui = { version = "0.5.0", features = ["pagination"] }

Usage

use leptos::prelude::*;
use biji_ui::components::pagination;

#[component]
pub fn MyPagination() -> impl IntoView {
    let page = RwSignal::new(1_i32);
    let total = RwSignal::new(100_i32);

    view! {
        <pagination::RootWith
            class="flex gap-2 items-center"
            page=page
            page_size=20
            total=total
            let:p
        >
            <button
                disabled=move || !p.has_prev.get()
                on:click=move |_| page.update(|n| *n -= 1)
                class="px-3 py-1.5 rounded border border-border disabled:opacity-50"
            >
                "Previous"
            </button>
            <span class="text-sm text-muted-foreground">
                {move || format!("Page {} of {}", p.page.get(), p.total_pages.get())}
            </span>
            <button
                disabled=move || !p.has_next.get()
                on:click=move |_| page.update(|n| *n += 1)
                class="px-3 py-1.5 rounded border border-border disabled:opacity-50"
            >
                "Next"
            </button>
        </pagination::RootWith>
    }
}

use_pagination()

Use use_pagination() inside any descendant of <Root> to retrieve PaginationState from context. Prefer this when your controls live in a separate component.

use leptos::prelude::*;
use biji_ui::components::pagination::{self, use_pagination};

// Child component reads state from context via use_pagination()
#[component]
fn PageInfo() -> impl IntoView {
    let p = use_pagination();
    view! {
        <span class="text-sm tabular-nums text-muted-foreground">
            {move || format!(
                "Showing {}\u{2013}{} of {}",
                p.offset.get() + 1,
                (p.offset.get() + p.page_size).min(p.total.get()),
                p.total.get(),
            )}
        </span>
    }
}

#[component]
pub fn TableFooter() -> impl IntoView {
    let page = RwSignal::new(1_i32);
    let total = RwSignal::new(47_i32);

    view! {
        <pagination::Root
            class="flex justify-between items-center"
            page=page
            page_size=10
            total=total
        >
            <PageInfo />
            // ... prev/next buttons
        </pagination::Root>
    }
}

API Reference

Root / RootWith

NameTypeDefaultDescription
pageSignal<i32>Current 1-indexed page number. Accepts an RwSignal or any Signal<i32>.
page_sizei32Number of items per page.
totalSignal<i32>Total number of items. Accepts a static i32 or a reactive signal.
classString""CSS class applied to the root <nav> element.

PaginationState

NameTypeDefaultDescription
pageSignal<i32>Current 1-indexed page number (mirrors the prop).
page_sizei32Items per page (mirrors the prop).
totalSignal<i32>Total item count (mirrors the prop).
total_pagesSignal<i32>Derived total number of pages.
has_nextSignal<bool>Whether a next page exists.
has_prevSignal<bool>Whether a previous page exists.
offsetSignal<i32>0-based index of the first item on the current page. Use as a query offset.

Data Attributes

AttributeDescription
data-pageThe current page number as a string. Present on the root <nav> element.
data-total-pagesThe total number of pages as a string. Present on the root <nav> element.