Skip to main content

dioxus_element_plug/components/
notification.rs

1use dioxus::prelude::*;
2
3// Notification CSS class constants
4pub const NOTIFICATION: &str = "el-notification";
5
6/// Notification types matching theme-chalk styles
7#[derive(Clone, PartialEq)]
8pub enum NotificationType {
9    Success,
10    Warning,
11    Info,
12    Error,
13}
14
15impl NotificationType {
16    pub fn as_class(&self) -> &'static str {
17        match self {
18            NotificationType::Success => "el-notification--success",
19            NotificationType::Warning => "el-notification--warning",
20            NotificationType::Info => "el-notification--info",
21            NotificationType::Error => "el-notification--error",
22        }
23    }
24}
25
26/// Notification props
27#[derive(Props, Clone, PartialEq)]
28pub struct NotificationProps {
29    /// Notification title
30    pub title: String,
31
32    /// Notification message
33    pub message: String,
34
35    /// Notification type
36    #[props(default = NotificationType::Info)]
37    pub notification_type: NotificationType,
38
39    /// Position of the notification
40    #[props(default = "top-right".to_string())]
41    pub position: String,
42
43    /// Auto close timeout in milliseconds (0 to disable)
44    #[props(default = 4500)]
45    pub duration: u64,
46
47    /// Whether the notification can be closed manually
48    #[props(default = true)]
49    pub closable: bool,
50
51    /// Whether to show icon
52    #[props(default = true)]
53    pub show_icon: bool,
54
55    /// Additional CSS classes
56    #[props(default)]
57    pub class: Option<String>,
58
59    /// Inline styles
60    #[props(default)]
61    pub style: Option<String>,
62
63    /// Close event handler
64    #[props(default)]
65    pub on_close: Option<EventHandler<()>>,
66}
67
68/// A notification component for temporary messages
69///
70/// This component creates a temporary notification that can auto-close
71/// after a specified duration.
72#[component]
73pub fn Notification(props: NotificationProps) -> Element {
74    let mut class_names = vec![NOTIFICATION.to_string()];
75
76    class_names.push(props.notification_type.as_class().to_string());
77
78    class_names.push(format!("is-{}", props.position));
79
80    if let Some(ref custom_class) = props.class {
81        class_names.push(custom_class.to_string());
82    }
83
84    let class_string = class_names.join(" ");
85    let style_string = props.style.as_ref().cloned().unwrap_or_default();
86
87    let icon_class = match props.notification_type {
88        NotificationType::Success => "el-icon-check-circle",
89        NotificationType::Warning => "el-icon-warning-outline",
90        NotificationType::Info => "el-icon-info-circle",
91        NotificationType::Error => "el-icon-error-circle",
92    };
93
94    rsx! {
95        div {
96            class: "{class_string}",
97            style: "{style_string}",
98            role: "alert",
99
100            div {
101                class: "el-notification__content",
102
103                if props.show_icon {
104                    i {
105                        class: "{icon_class} el-notification__icon"
106                    }
107                }
108
109                div {
110                    class: "el-notification__group",
111
112                    h3 {
113                        class: "el-notification__title",
114                        "{props.title}"
115                    }
116
117                    div {
118                        class: "el-notification__message",
119                        "{props.message}"
120                    }
121                }
122            }
123
124            if props.closable {
125                button {
126                    class: "el-notification__close-btn",
127                    r#type: "button",
128                    onclick: move |_| {
129                        if let Some(handler) = props.on_close {
130                            handler.call(());
131                        }
132                    },
133                    "×"
134                }
135            }
136        }
137    }
138}