yew_nav_link/components/badge.rs
1//! # `NavBadge`
2//!
3//! Small colored label for showing counts, statuses, or labels inside
4//! navigation links. Renders a `<span>` you can place anywhere inside
5//! a `NavLink` or `NavItem`.
6//!
7//! # Quick Start
8//!
9//! ```rust
10//! use yew::prelude::*;
11//! use yew_nav_link::{NavBadge, NavItem, NavLink, NavList};
12//! use yew_router::prelude::*;
13//!
14//! # #[derive(Clone, PartialEq, Routable)]
15//! # enum Route {
16//! # #[at("/")]
17//! # Home,
18//! # }
19//! #[component]
20//! fn Nav() -> Html {
21//! html! {
22//! <NavList>
23//! <NavItem>
24//! <NavLink<Route> to={Route::Home}>
25//! { "Messages " }
26//! <NavBadge variant="danger">{ "3" }</NavBadge>
27//! </NavLink<Route>>
28//! </NavItem>
29//! </NavList>
30//! }
31//! }
32//! ```
33//!
34//! Available variants: `"primary"`, `"success"`, `"warning"`, `"danger"`.
35//! Set `pill=true` for fully rounded corners.
36//!
37//! # CSS Classes
38//!
39//! | Class | When Applied |
40//! |-------|--------------|
41//! | `nav-badge` | Always |
42//! | `nav-badge-pill` | When `pill` is `true` |
43//! | `nav-badge-{variant}` | Based on the `variant` prop |
44//!
45//! # Props
46//!
47//! | Prop | Type | Default | Description |
48//! |------|------|---------|-------------|
49//! | `variant` | `&'static str` | `"primary"` | Color variant |
50//! | `pill` | `bool` | `false` | Rounded pill shape |
51//! | `classes` | `Classes` | — | Additional CSS classes |
52//! | `children` | `Children` | — | Badge content |
53
54use yew::prelude::*;
55
56/// Properties for the [`NavBadge`] component.
57///
58/// | Prop | Type | Default | Description |
59/// |------|------|---------|-------------|
60/// | `variant` | `&'static str` | `"primary"` | Visual variant name |
61/// | `pill` | `bool` | `false` | Pill-shaped corners |
62/// | `classes` | `Classes` | — | Additional CSS classes |
63/// | `children` | `Children` | — | Badge content |
64#[derive(Properties, Clone, PartialEq, Debug)]
65pub struct NavBadgeProps {
66 /// Additional CSS classes applied to the badge.
67 #[prop_or_default]
68 pub classes: Classes,
69
70 /// Visual variant name, e.g. `"primary"`, `"success"`, `"danger"`.
71 #[prop_or("primary")]
72 pub variant: &'static str,
73
74 /// Render the badge with pill-shaped (fully rounded) corners.
75 #[prop_or_default]
76 pub pill: bool,
77
78 /// Content rendered inside the badge.
79 #[prop_or_default]
80 pub children: Children
81}
82
83/// Badge component for displaying status or count indicators on navigation
84/// items.
85///
86/// # CSS Classes
87///
88/// - `nav-badge` - Always applied
89/// - `nav-badge-pill` - Applied when `pill` is `true`
90/// - `nav-badge-{variant}` - Applied based on the `variant` prop
91#[function_component]
92pub fn NavBadge(props: &NavBadgeProps) -> Html {
93 let mut classes = props.classes.clone();
94 classes.push("nav-badge");
95
96 if props.pill {
97 classes.push("nav-badge-pill");
98 }
99
100 let variant_class = format!("nav-badge-{}", props.variant);
101 classes.push(variant_class);
102
103 html! {
104 <span {classes}>
105 { for props.children.iter() }
106 </span>
107 }
108}
109
110#[cfg(test)]
111mod tests {
112 use super::*;
113
114 #[test]
115 fn nav_badge_props_default() {
116 let props = NavBadgeProps {
117 classes: Classes::default(),
118 variant: "primary",
119 pill: false,
120 children: Children::new(vec![])
121 };
122
123 assert!(!props.pill);
124 assert_eq!(props.variant, "primary");
125 }
126
127 #[test]
128 fn nav_badge_clone() {
129 let props1 = NavBadgeProps {
130 classes: Classes::from("test"),
131 variant: "success",
132 pill: true,
133 children: Children::new(vec![])
134 };
135
136 let props2 = props1.clone();
137 assert_eq!(props1.variant, props2.variant);
138 assert_eq!(props1.pill, props2.pill);
139 }
140}