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