Skip to main content

yew_nav_link/components/
page_item.rs

1// SPDX-FileCopyrightText: 2024-2026 RAprogramm <andrey.rozanov-vl@gmail.com>
2// SPDX-License-Identifier: MIT
3
4//! # `PageItem`
5//!
6//! A single page button within a [`Pagination`](super::Pagination) component.
7//! Renders an `<li>` with the `page-item` class and active/disabled state.
8//!
9//! # Example
10//!
11//! ```rust
12//! use yew::prelude::*;
13//! use yew_nav_link::components::{PageItem, PageLink};
14//!
15//! #[component]
16//! fn PaginationNav() -> Html {
17//!     html! {
18//!         <nav><ul class="pagination">
19//!             <PageItem page={1} active=true>
20//!                 <PageLink href={None}>{ "1" }</PageLink>
21//!             </PageItem>
22//!             <PageItem page={2}>
23//!                 <PageLink href={Some("/page/2")}>{ "2" }</PageLink>
24//!             </PageItem>
25//!         </ul></nav>
26//!     }
27//! }
28//! ```
29//!
30//! # CSS Classes
31//!
32//! | Class | Condition |
33//! |-------|-----------|
34//! | `page-item` | Always applied |
35//! | `active` | Applied when `active` is `true` |
36//! | `disabled` | Applied when `disabled` is `true` |
37//!
38//! # Props
39//!
40//! | Prop | Type | Default | Description |
41//! |------|------|---------|-------------|
42//! | `page` | `u32` | — | Page number (required) |
43//! | `active` | `bool` | `false` | Currently active page |
44//! | `disabled` | `bool` | `false` | Disabled state |
45//! | `classes` | `Classes` | — | Additional CSS classes |
46//! | `children` | `Children` | — | Content |
47
48use yew::prelude::*;
49
50/// Properties for the [`PageItem`] component.
51///
52/// | Prop | Type | Default | Description |
53/// |------|------|---------|-------------|
54/// | `page` | `u32` | — | Page number (required) |
55/// | `active` | `bool` | `false` | Currently active page |
56/// | `disabled` | `bool` | `false` | Disabled state |
57/// | `classes` | `Classes` | — | Additional CSS classes |
58/// | `children` | `Children` | — | Content |
59#[derive(Properties, Clone, PartialEq, Debug)]
60pub struct PageItemProps {
61    /// Additional CSS classes applied to the page item.
62    #[prop_or_default]
63    pub classes: Classes,
64
65    /// Page number this item represents.
66    pub page: u32,
67
68    /// Whether this page item is the currently active page.
69    #[prop_or(false)]
70    pub active: bool,
71
72    /// Whether this page item is disabled (e.g. an ellipsis).
73    #[prop_or(false)]
74    pub disabled: bool,
75
76    /// Content rendered inside the page item.
77    #[prop_or_default]
78    pub children: Children
79}
80
81/// A single page button within a [`Pagination`](super::Pagination) component.
82///
83/// # CSS Classes
84///
85/// - `page-item` - Always applied
86/// - `active` - Applied when `active` is `true`
87/// - `disabled` - Applied when `disabled` is `true`
88#[function_component]
89pub fn PageItem(props: &PageItemProps) -> Html {
90    let mut classes = props.classes.clone();
91    classes.push("page-item");
92
93    if props.active {
94        classes.push("active");
95    }
96
97    if props.disabled {
98        classes.push("disabled");
99    }
100
101    html! {
102        <li {classes}>
103            <span class="page-link">
104                { for props.children.iter() }
105            </span>
106        </li>
107    }
108}
109
110#[cfg(test)]
111mod tests {
112    use super::*;
113
114    #[test]
115    fn page_item_props() {
116        let props = PageItemProps {
117            classes:  Classes::default(),
118            page:     1,
119            active:   false,
120            disabled: false,
121            children: Children::new(vec![])
122        };
123
124        assert_eq!(props.page, 1);
125        assert!(!props.active);
126        assert!(!props.disabled);
127    }
128}