Skip to main content

dioxus_bootstrap_css/
collapse.rs

1use dioxus::prelude::*;
2
3/// Bootstrap Collapse component — signal-driven, no JavaScript.
4///
5/// # Bootstrap HTML → Dioxus
6///
7/// ```html
8/// <!-- Bootstrap HTML (requires JavaScript) -->
9/// <button data-bs-toggle="collapse" data-bs-target="#content">Toggle</button>
10/// <div class="collapse" id="content">Hidden content</div>
11/// ```
12///
13/// ```rust,no_run
14/// # use dioxus::prelude::*;
15/// # use dioxus_bootstrap_css::prelude::*;
16/// # fn _doctest() -> Element {
17/// // Dioxus equivalent
18/// let mut expanded = use_signal(|| false);
19/// rsx! {
20///     Button { onclick: move |_| expanded.toggle(), "Toggle Content" }
21///     Collapse { expanded: expanded,
22///         Card { body: rsx! { "Collapsible content here." } }
23///     }
24/// }
25/// # }
26/// ```
27///
28/// # Props
29///
30/// - `expanded` — `Signal<bool>` controlling expanded/collapsed state
31/// - `horizontal` — horizontal collapse instead of vertical
32#[derive(Clone, PartialEq, Props)]
33pub struct CollapseProps {
34    /// Signal controlling expanded/collapsed state.
35    pub expanded: Signal<bool>,
36    /// Use horizontal collapse instead of vertical.
37    #[props(default)]
38    pub horizontal: bool,
39    /// Additional CSS classes.
40    #[props(default)]
41    pub class: String,
42    /// Child elements.
43    pub children: Element,
44}
45
46#[component]
47pub fn Collapse(props: CollapseProps) -> Element {
48    let is_expanded = *props.expanded.read();
49
50    let horizontal = if props.horizontal {
51        " collapse-horizontal"
52    } else {
53        ""
54    };
55
56    let show = if is_expanded { " show" } else { "" };
57
58    let full_class = if props.class.is_empty() {
59        format!("collapse{horizontal}{show}")
60    } else {
61        format!("collapse{horizontal}{show} {}", props.class)
62    };
63
64    rsx! {
65        div { class: "{full_class}",
66            {props.children}
67        }
68    }
69}