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/// # Bootstrap HTML → Dioxus
6///
7/// ```html
8/// <!-- Bootstrap HTML -->
9/// <div class="card">
10///   <div class="card-header">Title</div>
11///   <div class="card-body"><p>Content</p></div>
12///   <div class="card-footer">Footer</div>
13/// </div>
14/// ```
15///
16/// ```rust,no_run
17/// // Dioxus equivalent
18/// rsx! {
19///     Card {
20///         header: rsx! { "Card Title" },
21///         body: rsx! { p { "Card content goes here." } },
22///         footer: rsx! { "Last updated 3 mins ago" },
23///     }
24///     // Body-only card
25///     Card { body: rsx! { "Simple card" } }
26///     // Custom layout (children go inside card, outside body)
27///     Card { class: "text-center",
28///         img { class: "card-img-top", src: "/photo.jpg" }
29///         div { class: "card-body", h5 { "Title" } p { "Text" } }
30///     }
31/// }
32/// ```
33#[derive(Clone, PartialEq, Props)]
34pub struct CardProps {
35    /// Card header content.
36    #[props(default)]
37    pub header: Option<Element>,
38    /// Card body content.
39    #[props(default)]
40    pub body: Option<Element>,
41    /// Card footer content.
42    #[props(default)]
43    pub footer: Option<Element>,
44    /// Additional CSS classes for the card container.
45    #[props(default)]
46    pub class: String,
47    /// Additional CSS classes for the card body.
48    #[props(default)]
49    pub body_class: String,
50    /// Child elements (rendered inside card, outside body — for custom layouts).
51    #[props(default)]
52    pub children: Element,
53}
54
55#[component]
56pub fn Card(props: CardProps) -> Element {
57    let full_class = if props.class.is_empty() {
58        "card".to_string()
59    } else {
60        format!("card {}", props.class)
61    };
62
63    let body_class = if props.body_class.is_empty() {
64        "card-body".to_string()
65    } else {
66        format!("card-body {}", props.body_class)
67    };
68
69    rsx! {
70        div { class: "{full_class}",
71            if let Some(header) = props.header {
72                div { class: "card-header", {header} }
73            }
74            if let Some(body) = props.body {
75                div { class: "{body_class}", {body} }
76            }
77            {props.children}
78            if let Some(footer) = props.footer {
79                div { class: "card-footer", {footer} }
80            }
81        }
82    }
83}