Pagination*
Rust/UI component that displays a pagination component.
navigation
- Copy Demo
use leptos::prelude::*;
use crate::components::ui::pagination::{
Pagination, PaginationActive, PaginationContent, PaginationEllipsis, PaginationItem, PaginationLink,
PaginationNext, PaginationPrevious,
};
#[component]
pub fn DemoPagination() -> impl IntoView {
view! {
<Pagination attr:role="navigation" attr:aria-label="pagination">
<PaginationContent>
<PaginationItem>
<PaginationPrevious href="#" />
</PaginationItem>
<PaginationItem>
<PaginationLink attr:href="#">1</PaginationLink>
</PaginationItem>
<PaginationItem>
<PaginationActive attr:aria-current="page" attr:data-active="true" attr:href="#">
2
</PaginationActive>
</PaginationItem>
<PaginationItem>
<PaginationLink attr:href="#">3</PaginationLink>
</PaginationItem>
<PaginationItem>
<PaginationEllipsis />
</PaginationItem>
<PaginationItem>
<PaginationNext href="#" />
</PaginationItem>
</PaginationContent>
</Pagination>
}
}
Installation
You can run either of the following commands:
# cargo install ui-cli --forceui add demo_paginationui add pagination
Update the imports to match your project setup.
Copy and paste the following code into your project:
components/ui/pagination.rs
use icons::{ChevronLeft, ChevronRight, Ellipsis};
use leptos::prelude::*;
use leptos_ui::clx;
use leptos_ui::clx::IntoTailwindClass;
use crate::registry::ui::button::{ButtonClass, ButtonSize, ButtonVariant};
mod components {
use super::*;
clx! {Pagination, nav, "flex justify-center mx-auto w-full"}
clx! {PaginationContent, ul, "flex flex-row gap-1 items-center"}
clx! {PaginationItem, li, ""}
clx! {EllipsisRoot, span, "flex justify-center items-center size-9 [&_svg:not([class*='size-'])]:size-4"}
const COMMON_CLASSES: &str = "inline-flex justify-center items-center text-sm font-medium whitespace-nowrap rounded-md outline-none hover:bg-accent hover:text-accent-foreground transition-all disabled:opacity-50 disabled:pointer-events-none [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 aria-invalid:ring-destructive/20 aria-invalid:border-destructive dark:aria-invalid:ring-destructive/40 focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]";
// TODO. Merge common classes first.
clx! {PaginationLink, a, COMMON_CLASSES, "gap-2 size-9 dark:hover:bg-accent/50"}
clx! {PaginationActive, a, COMMON_CLASSES, "gap-2 border bg-background shadow-xs size-9 dark:bg-input/30 dark:border-input dark:hover:bg-input/50"}
clx! {RootPrevious, a, COMMON_CLASSES, "py-2 has-[>svg]:px-3 dark:hover:bg-accent/50"}
clx! {RootNext, a, COMMON_CLASSES, "h-9 has-[>svg]:px-3 dark:hover:bg-accent/50"}
}
pub use components::*;
/* ========================================================== */
/* ✨ FUNCTIONS ✨ */
/* ========================================================== */
#[component]
pub fn PaginationNext(href: &'static str) -> impl IntoView {
view! {
<RootNext class="gap-1 py-2 px-2.5 sm:pr-2.5" attr:aria-label="Go to next page" attr:href=href>
<span class="hidden sm:block">Next</span>
<ChevronRight />
</RootNext>
}
}
#[component]
pub fn PaginationPrevious(href: &'static str) -> impl IntoView {
view! {
<RootPrevious class="gap-1 px-2.5 h-9 sm:pl-2.5" attr:aria-label="Go to previous page" attr:href=href>
<ChevronLeft />
<span class="hidden sm:block">Previous</span>
</RootPrevious>
}
}
#[component]
pub fn PaginationEllipsis() -> impl IntoView {
view! {
<EllipsisRoot attr:aria-hidden="true">
<Ellipsis />
<span class="sr-only">More pages</span>
</EllipsisRoot>
}
}
/* ========================================================== */
/* ✨ FUNCTIONS ✨ */
/* ========================================================== */
// TODO. Merge properly with Button
#[component]
pub fn PaginationLinkWithButton(
#[prop(into, optional)] variant: Signal<ButtonVariant>,
#[prop(into, optional)] size: Signal<ButtonSize>,
#[prop(into, optional)] class: String,
#[prop(into, optional)] _is_active: Option<bool>,
#[prop(into)] href: &'static str,
children: Children,
) -> impl IntoView {
// TODO. should be ButtonVariant::Ghost OR ButtonVariant::Outline if is_active
let merged_class = Memo::new(move |_| {
let variant = variant.get();
let size = size.get();
let button = ButtonClass { variant, size };
button.with_class(class.clone())
});
view! {
<a class=merged_class href=href>
{children()}
</a>
}
}
Update the imports to match your project setup.
Usage
// Coming soon 🦀