Skip to main content

dioxus_bootstrap_css/
alert.rs

1use dioxus::prelude::*;
2
3use crate::types::Color;
4
5/// Bootstrap Alert component.
6///
7/// # Bootstrap HTML → Dioxus
8///
9/// | HTML | Dioxus |
10/// |---|---|
11/// | `<div class="alert alert-success">` | `Alert { color: Color::Success, "Text" }` |
12/// | `<div class="alert alert-danger alert-dismissible">` | `Alert { color: Color::Danger, dismissible: true, "Text" }` |
13///
14/// ```rust,no_run
15/// rsx! {
16///     Alert { color: Color::Success, "Operation completed!" }
17///     Alert { color: Color::Danger, dismissible: true,
18///         strong { "Error! " }
19///         "Something went wrong."
20///     }
21///     // With dismiss callback:
22///     Alert { color: Color::Warning, dismissible: true,
23///         on_dismiss: move |_| { /* clear error state */ },
24///         "Dismissible with callback."
25///     }
26/// }
27/// ```
28#[derive(Clone, PartialEq, Props)]
29pub struct AlertProps {
30    /// Alert color variant.
31    #[props(default = Color::Primary)]
32    pub color: Color,
33    /// Show a dismiss button. When clicked, the alert hides itself.
34    #[props(default)]
35    pub dismissible: bool,
36    /// Callback when the dismiss button is clicked. Use this to clear external state.
37    #[props(default)]
38    pub on_dismiss: Option<EventHandler<()>>,
39    /// Additional CSS classes.
40    #[props(default)]
41    pub class: String,
42    /// Any additional HTML attributes.
43    #[props(extends = GlobalAttributes)]
44    attributes: Vec<Attribute>,
45    /// Child elements.
46    pub children: Element,
47}
48
49#[component]
50pub fn Alert(props: AlertProps) -> Element {
51    let mut visible = use_signal(|| true);
52
53    if !*visible.read() {
54        return rsx! {};
55    }
56
57    let dismiss_class = if props.dismissible {
58        " alert-dismissible fade show"
59    } else {
60        ""
61    };
62
63    let full_class = if props.class.is_empty() {
64        format!("alert alert-{}{dismiss_class}", props.color)
65    } else {
66        format!("alert alert-{}{dismiss_class} {}", props.color, props.class)
67    };
68
69    rsx! {
70        div {
71            class: "{full_class}",
72            role: "alert",
73            ..props.attributes,
74            {props.children}
75            if props.dismissible {
76                button {
77                    class: "btn-close",
78                    r#type: "button",
79                    "aria-label": "Close",
80                    onclick: move |_| {
81                        visible.set(false);
82                        if let Some(handler) = &props.on_dismiss {
83                            handler.call(());
84                        }
85                    },
86                }
87            }
88        }
89    }
90}