Skip to main content

dioxus_bootstrap_css/
card.rs

1use dioxus::prelude::*;
2
3/// Bootstrap Card component with optional header, body, and footer slots.
4///
5/// ```rust
6/// rsx! {
7///     Card {
8///         header: rsx! { "Card Title" },
9///         body: rsx! { p { "Card content goes here." } },
10///         footer: rsx! { "Last updated 3 mins ago" },
11///     }
12///     // Body-only card
13///     Card {
14///         body: rsx! { "Simple card" },
15///     }
16/// }
17/// ```
18#[derive(Clone, PartialEq, Props)]
19pub struct CardProps {
20    /// Card header content.
21    #[props(default)]
22    pub header: Option<Element>,
23    /// Card body content.
24    #[props(default)]
25    pub body: Option<Element>,
26    /// Card footer content.
27    #[props(default)]
28    pub footer: Option<Element>,
29    /// Additional CSS classes for the card container.
30    #[props(default)]
31    pub class: String,
32    /// Additional CSS classes for the card body.
33    #[props(default)]
34    pub body_class: String,
35    /// Child elements (rendered inside card, outside body — for custom layouts).
36    #[props(default)]
37    pub children: Element,
38}
39
40#[component]
41pub fn Card(props: CardProps) -> Element {
42    let full_class = if props.class.is_empty() {
43        "card".to_string()
44    } else {
45        format!("card {}", props.class)
46    };
47
48    let body_class = if props.body_class.is_empty() {
49        "card-body".to_string()
50    } else {
51        format!("card-body {}", props.body_class)
52    };
53
54    rsx! {
55        div { class: "{full_class}",
56            if let Some(header) = props.header {
57                div { class: "card-header", {header} }
58            }
59            if let Some(body) = props.body {
60                div { class: "{body_class}", {body} }
61            }
62            {props.children}
63            if let Some(footer) = props.footer {
64                div { class: "card-footer", {footer} }
65            }
66        }
67    }
68}