yew_nav_link/components/header.rs
1// SPDX-FileCopyrightText: 2024-2026 RAprogramm <andrey.rozanov-vl@gmail.com>
2// SPDX-License-Identifier: MIT
3
4//! # `NavHeader`
5//!
6//! Section header for labeling groups within a navigation list.
7//! Renders a `<li>` with `role="presentation"` and the `nav-header` class.
8//!
9//! # Example
10//!
11//! ```rust
12//! use yew::prelude::*;
13//! use yew_nav_link::{NavHeader, NavItem, NavLink, NavList};
14//! use yew_router::prelude::*;
15//!
16//! # #[derive(Clone, PartialEq, Routable)]
17//! # enum Route {
18//! # #[at("/")]
19//! # Home,
20//! # #[at("/about")]
21//! # About,
22//! # }
23//! #[component]
24//! fn Nav() -> Html {
25//! html! {
26//! <NavList>
27//! <NavHeader text="Main" />
28//! <NavItem><NavLink<Route> to={Route::Home}>{ "Home" }</NavLink<Route>></NavItem>
29//! <NavHeader text="Info" />
30//! <NavItem><NavLink<Route> to={Route::About}>{ "About" }</NavLink<Route>></NavItem>
31//! </NavList>
32//! }
33//! }
34//! ```
35//!
36//! # CSS Classes
37//!
38//! | Class | Condition |
39//! |-------|-----------|
40//! | `nav-header` | Always applied |
41//! | `nav-header-text` | Inner text span |
42//!
43//! # Props
44//!
45//! | Prop | Type | Default | Description |
46//! |------|------|---------|-------------|
47//! | `text` | `Option<&'static str>` | `None` | Header text label |
48//! | `classes` | `Classes` | — | Additional CSS classes |
49//! | `children` | `Children` | — | Content when `text` is `None` |
50
51use yew::prelude::*;
52
53/// Properties for the [`NavHeader`] component.
54///
55/// | Prop | Type | Default | Description |
56/// |------|------|---------|-------------|
57/// | `text` | `Option<&'static str>` | `None` | Header text label |
58/// | `classes` | `Classes` | — | Additional CSS classes |
59/// | `children` | `Children` | — | Content when `text` is `None` |
60#[derive(Properties, Clone, PartialEq, Debug)]
61pub struct NavHeaderProps {
62 /// Additional CSS classes applied to the header.
63 #[prop_or_default]
64 pub classes: Classes,
65
66 /// Text label displayed in the header. If set, overrides `children`.
67 #[prop_or_default]
68 pub text: Option<&'static str>,
69
70 /// Content rendered inside the header when `text` is `None`.
71 #[prop_or_default]
72 pub children: Children
73}
74
75/// Header component for labeling sections within a navigation list.
76///
77/// Renders a `<li>` with `role="presentation"` and the `nav-header` class.
78#[function_component]
79pub fn NavHeader(props: &NavHeaderProps) -> Html {
80 let mut classes = props.classes.clone();
81 classes.push("nav-header");
82
83 if let Some(text) = props.text {
84 html! {
85 <li {classes} role="presentation">
86 <span class="nav-header-text">{ text }</span>
87 </li>
88 }
89 } else {
90 html! {
91 <li {classes} role="presentation">
92 { for props.children.iter() }
93 </li>
94 }
95 }
96}
97
98#[cfg(test)]
99mod tests {
100 use super::*;
101
102 #[test]
103 fn nav_header_props_with_text() {
104 let props = NavHeaderProps {
105 classes: Classes::default(),
106 text: Some("Header"),
107 children: Children::new(vec![])
108 };
109
110 assert_eq!(props.text, Some("Header"));
111 }
112
113 #[test]
114 fn nav_header_clone() {
115 let props1 = NavHeaderProps {
116 classes: Classes::default(),
117 text: Some("Header"),
118 children: Children::new(vec![])
119 };
120
121 let props2 = props1.clone();
122 assert_eq!(props1.text, props2.text);
123 }
124}