Skip to main content

dioxus_bootstrap_css/
breadcrumb.rs

1use dioxus::prelude::*;
2
3/// Bootstrap Breadcrumb component.
4///
5/// # Bootstrap HTML → Dioxus
6///
7/// | HTML | Dioxus |
8/// |---|---|
9/// | `<nav><ol class="breadcrumb"><li class="breadcrumb-item"><a href="/">Home</a></li>...` | `Breadcrumb { BreadcrumbItem { href: "/", "Home" } ... }` |
10/// | `<li class="breadcrumb-item active" aria-current="page">Current</li>` | `BreadcrumbItem { active: true, "Current" }` |
11///
12/// ```rust,no_run
13/// # use dioxus::prelude::*;
14/// # use dioxus_bootstrap_css::prelude::*;
15/// # fn _doctest() -> Element {
16/// rsx! {
17///     Breadcrumb {
18///         BreadcrumbItem { href: "/", "Home" }
19///         BreadcrumbItem { href: "/products", "Products" }
20///         BreadcrumbItem { active: true, "Current Page" }
21///     }
22/// }
23/// # }
24/// ```
25#[derive(Clone, PartialEq, Props)]
26pub struct BreadcrumbProps {
27    /// Additional CSS classes.
28    #[props(default)]
29    pub class: String,
30    /// Child elements (BreadcrumbItem components).
31    pub children: Element,
32}
33
34#[component]
35pub fn Breadcrumb(props: BreadcrumbProps) -> Element {
36    let full_class = if props.class.is_empty() {
37        "breadcrumb".to_string()
38    } else {
39        format!("breadcrumb {}", props.class)
40    };
41
42    rsx! {
43        nav { "aria-label": "breadcrumb",
44            ol { class: "{full_class}", {props.children} }
45        }
46    }
47}
48
49/// A single item in a Breadcrumb.
50#[derive(Clone, PartialEq, Props)]
51pub struct BreadcrumbItemProps {
52    /// Link href. Not rendered if active.
53    #[props(default)]
54    pub href: String,
55    /// Active (current page) state — renders as plain text instead of link.
56    #[props(default)]
57    pub active: bool,
58    /// Click handler for the link. A breadcrumb in a single-page app navigates
59    /// by handler rather than by `href`, and without this the only way to
60    /// intercept it is to hand-write the `<a>` — which is the raw Bootstrap the
61    /// component exists to replace.
62    #[props(default)]
63    pub onclick: Option<EventHandler<MouseEvent>>,
64    /// Additional CSS classes.
65    #[props(default)]
66    pub class: String,
67    /// Child elements.
68    pub children: Element,
69}
70
71#[component]
72pub fn BreadcrumbItem(props: BreadcrumbItemProps) -> Element {
73    let mut classes = vec!["breadcrumb-item".to_string()];
74    if props.active {
75        classes.push("active".to_string());
76    }
77    if !props.class.is_empty() {
78        classes.push(props.class.clone());
79    }
80    let full_class = classes.join(" ");
81
82    if props.active {
83        rsx! {
84            li {
85                class: "{full_class}",
86                "aria-current": "page",
87                {props.children}
88            }
89        }
90    } else {
91        rsx! {
92            li { class: "{full_class}",
93                a {
94                    href: "{props.href}",
95                    onclick: move |evt| {
96                        if let Some(handler) = &props.onclick {
97                            handler.call(evt);
98                        }
99                    },
100                    {props.children}
101                }
102            }
103        }
104    }
105}