dioxus_bootstrap_css/
nav.rs1use dioxus::prelude::*;
2
3use crate::types::{Color, NavbarExpand};
4
5#[derive(Clone, PartialEq, Props)]
43pub struct NavProps {
44 #[props(default)]
46 pub pills: bool,
47 #[props(default)]
49 pub tabs: bool,
50 #[props(default)]
52 pub underline: bool,
53 #[props(default)]
55 pub fill: bool,
56 #[props(default)]
58 pub justified: bool,
59 #[props(default)]
61 pub vertical: bool,
62 #[props(default)]
64 pub class: String,
65 pub children: Element,
67}
68
69#[component]
70pub fn Nav(props: NavProps) -> Element {
71 let mut classes = vec!["nav".to_string()];
72 if props.pills {
73 classes.push("nav-pills".to_string());
74 }
75 if props.tabs {
76 classes.push("nav-tabs".to_string());
77 }
78 if props.underline {
79 classes.push("nav-underline".to_string());
80 }
81 if props.fill {
82 classes.push("nav-fill".to_string());
83 }
84 if props.justified {
85 classes.push("nav-justified".to_string());
86 }
87 if props.vertical {
88 classes.push("flex-column".to_string());
89 }
90 if !props.class.is_empty() {
91 classes.push(props.class.clone());
92 }
93 let full_class = classes.join(" ");
94
95 rsx! {
96 ul { class: "{full_class}",
97 {props.children}
98 }
99 }
100}
101
102#[derive(Clone, PartialEq, Props)]
136pub struct NavbarProps {
137 #[props(default)]
139 pub color: Option<Color>,
140 #[props(default)]
142 pub expand: NavbarExpand,
143 #[props(default)]
145 pub brand: Option<Element>,
146 #[props(default)]
148 pub class: String,
149 pub children: Element,
151}
152
153#[component]
154pub fn Navbar(props: NavbarProps) -> Element {
155 let mut classes = vec!["navbar".to_string(), props.expand.to_string()];
156
157 if let Some(ref color) = props.color {
158 match color {
159 Color::Dark => {
160 classes.push("bg-dark".to_string());
161 classes.push("[data-bs-theme=dark]".to_string());
162 }
163 Color::Light => {
164 classes.push("bg-light".to_string());
165 }
166 c => {
167 classes.push(format!("bg-{c}"));
168 }
169 }
170 }
171
172 if !props.class.is_empty() {
173 classes.push(props.class.clone());
174 }
175
176 let full_class = classes.join(" ");
177
178 rsx! {
179 nav { class: "{full_class}",
180 div { class: "container-fluid",
181 if let Some(brand) = props.brand {
182 {brand}
183 }
184 {props.children}
185 }
186 }
187 }
188}
189
190#[derive(Clone, PartialEq, Props)]
198pub struct NavbarTogglerProps {
199 pub collapsed: Signal<bool>,
201 #[props(default)]
203 pub class: String,
204}
205
206#[component]
207pub fn NavbarToggler(props: NavbarTogglerProps) -> Element {
208 let is_collapsed = *props.collapsed.read();
209 let mut signal = props.collapsed;
210
211 let full_class = if props.class.is_empty() {
212 "navbar-toggler".to_string()
213 } else {
214 format!("navbar-toggler {}", props.class)
215 };
216
217 rsx! {
218 button {
219 class: "{full_class}",
220 r#type: "button",
221 "aria-expanded": if !is_collapsed { "true" } else { "false" },
222 "aria-label": "Toggle navigation",
223 onclick: move |_| signal.set(!is_collapsed),
224 span { class: "navbar-toggler-icon" }
225 }
226 }
227}
228
229#[derive(Clone, PartialEq, Props)]
241pub struct NavbarCollapseProps {
242 pub collapsed: Signal<bool>,
244 #[props(default)]
246 pub class: String,
247 pub children: Element,
249}
250
251#[component]
252pub fn NavbarCollapse(props: NavbarCollapseProps) -> Element {
253 let is_collapsed = *props.collapsed.read();
254 let show = if !is_collapsed { " show" } else { "" };
255
256 let full_class = if props.class.is_empty() {
257 format!("collapse navbar-collapse{show}")
258 } else {
259 format!("collapse navbar-collapse{show} {}", props.class)
260 };
261
262 rsx! {
263 div { class: "{full_class}",
264 ul { class: "navbar-nav me-auto mb-2 mb-lg-0",
265 {props.children}
266 }
267 }
268 }
269}
270
271#[derive(Clone, PartialEq, Props)]
273pub struct NavItemProps {
274 #[props(default)]
276 pub class: String,
277 pub children: Element,
279}
280
281#[component]
282pub fn NavItem(props: NavItemProps) -> Element {
283 let full_class = if props.class.is_empty() {
284 "nav-item".to_string()
285 } else {
286 format!("nav-item {}", props.class)
287 };
288
289 rsx! {
290 li { class: "{full_class}", {props.children} }
291 }
292}
293
294#[derive(Clone, PartialEq, Props)]
302pub struct NavLinkProps {
303 #[props(default = "#".to_string())]
305 pub href: String,
306 #[props(default)]
308 pub active: bool,
309 #[props(default)]
311 pub disabled: bool,
312 #[props(default)]
314 pub onclick: Option<EventHandler<MouseEvent>>,
315 #[props(default)]
317 pub class: String,
318 pub children: Element,
320}
321
322#[component]
323pub fn NavLink(props: NavLinkProps) -> Element {
324 let mut classes = vec!["nav-link".to_string()];
325 if props.active {
326 classes.push("active".to_string());
327 }
328 if props.disabled {
329 classes.push("disabled".to_string());
330 }
331 if !props.class.is_empty() {
332 classes.push(props.class.clone());
333 }
334 let full_class = classes.join(" ");
335
336 rsx! {
337 a {
338 class: "{full_class}",
339 href: "{props.href}",
340 "aria-current": if props.active { "page" } else { "" },
341 onclick: move |evt| {
342 if let Some(handler) = &props.onclick {
343 handler.call(evt);
344 }
345 },
346 {props.children}
347 }
348 }
349}