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/// // Dioxus equivalent
15/// let expanded = use_signal(|| false);
16/// rsx! {
17///     Button { onclick: move |_| expanded.toggle(), "Toggle Content" }
18///     Collapse { expanded: expanded,
19///         Card { body: rsx! { "Collapsible content here." } }
20///     }
21/// }
22/// ```
23///
24/// # Props
25///
26/// - `expanded` — `Signal<bool>` controlling expanded/collapsed state
27/// - `horizontal` — horizontal collapse instead of vertical
28#[derive(Clone, PartialEq, Props)]
29pub struct CollapseProps {
30    /// Signal controlling expanded/collapsed state.
31    pub expanded: Signal<bool>,
32    /// Use horizontal collapse instead of vertical.
33    #[props(default)]
34    pub horizontal: bool,
35    /// Additional CSS classes.
36    #[props(default)]
37    pub class: String,
38    /// Child elements.
39    pub children: Element,
40}
41
42#[component]
43pub fn Collapse(props: CollapseProps) -> Element {
44    let is_expanded = *props.expanded.read();
45
46    let horizontal = if props.horizontal {
47        " collapse-horizontal"
48    } else {
49        ""
50    };
51
52    let show = if is_expanded { " show" } else { "" };
53
54    let full_class = if props.class.is_empty() {
55        format!("collapse{horizontal}{show}")
56    } else {
57        format!("collapse{horizontal}{show} {}", props.class)
58    };
59
60    rsx! {
61        div { class: "{full_class}",
62            {props.children}
63        }
64    }
65}