1use crate::icon::{Icon, IconKind};
2use dioxus::prelude::*;
3
4#[derive(Clone, Copy, PartialEq, Debug, Default)]
5pub enum AlertVariant {
6 #[default]
7 Info,
8 Success,
9 Warning,
10 Danger,
11}
12
13impl AlertVariant {
14 pub fn scss_class(&self) -> &'static str {
15 match self {
16 AlertVariant::Info => "sd-alert--info",
17 AlertVariant::Success => "sd-alert--success",
18 AlertVariant::Warning => "sd-alert--warning",
19 AlertVariant::Danger => "sd-alert--danger",
20 }
21 }
22
23 pub fn name(&self) -> &'static str {
24 match self {
25 AlertVariant::Info => "info",
26 AlertVariant::Success => "success",
27 AlertVariant::Warning => "warning",
28 AlertVariant::Danger => "danger",
29 }
30 }
31
32 pub fn glow_class(&self) -> &'static str {
33 match self {
34 AlertVariant::Info => "sd-alert--glow-info",
35 AlertVariant::Success => "sd-alert--glow-success",
36 AlertVariant::Warning => "sd-alert--glow-warning",
37 AlertVariant::Danger => "sd-alert--glow-danger",
38 }
39 }
40
41 pub fn title_class(&self) -> &'static str {
42 match self {
43 AlertVariant::Info => "sd-alert__title--info",
44 AlertVariant::Success => "sd-alert__title--success",
45 AlertVariant::Warning => "sd-alert__title--warning",
46 AlertVariant::Danger => "sd-alert__title--danger",
47 }
48 }
49
50 pub fn icon_kind(&self) -> IconKind {
51 match self {
52 AlertVariant::Info => IconKind::Info,
53 AlertVariant::Success => IconKind::CheckCircle,
54 AlertVariant::Warning => IconKind::AlertTriangle,
55 AlertVariant::Danger => IconKind::XCircle,
56 }
57 }
58
59 pub fn icon_color_class(&self) -> &'static str {
60 match self {
61 AlertVariant::Info => "sd-alert__icon--info",
62 AlertVariant::Success => "sd-alert__icon--success",
63 AlertVariant::Warning => "sd-alert__icon--warning",
64 AlertVariant::Danger => "sd-alert__icon--danger",
65 }
66 }
67}
68
69#[component]
70pub fn Alert(
71 #[props(default)] title: Option<String>,
72 #[props(default)] variant: AlertVariant,
73 #[props(default)] class: String,
74 #[props(default)] glow: Option<bool>,
75 on_close: Option<EventHandler<MouseEvent>>,
76 children: Element,
77) -> Element {
78 let title_variant_class = variant.title_class();
79 let icon_color_class = variant.icon_color_class();
80
81 #[cfg(feature = "theme")]
82 let theme_val = crate::theme::use_theme()();
83 #[cfg(feature = "theme")]
84 let radius_class = theme_val.radius_scale.md();
85 #[cfg(feature = "theme")]
86 let base_override = theme_val.resolve_component_base("alert").unwrap_or("");
87 #[cfg(feature = "theme")]
88 let class_modifiers = theme_val.resolve_class_modifiers("alert", &class);
89 #[cfg(feature = "theme")]
90 let variant_class = theme_val.resolve_variant_class("alert", variant.name(), variant.scss_class());
91 #[cfg(feature = "theme")]
92 let glow_class = theme_val.resolve_elevation_class("alert", glow);
93
94 #[cfg(not(feature = "theme"))]
95 let base_override = "";
96 #[cfg(not(feature = "theme"))]
97 let class_modifiers = String::new();
98 #[cfg(not(feature = "theme"))]
99 let variant_class = variant.scss_class().to_string();
100 #[cfg(not(feature = "theme"))]
101 let radius_class = "";
102 #[cfg(not(feature = "theme"))]
103 let glow_class = if glow.unwrap_or(false) {
104 variant.glow_class().to_string()
105 } else {
106 String::new()
107 };
108
109 let icon_kind = variant.icon_kind();
110
111 rsx! {
112 div {
113 class: "sd-alert {base_override} {variant_class} {glow_class} {radius_class} {class_modifiers} {class}",
114 span { class: "sd-alert__icon {icon_color_class}",
115 Icon { kind: icon_kind, size: 18 }
116 }
117 div { class: "sd-alert__content",
118 if let Some(t) = title {
119 h4 { class: "sd-alert__title {title_variant_class}", "{t}" }
120 }
121 div { class: "sd-alert__body", {children} }
122 }
123 if let Some(close_handler) = on_close {
124 button {
125 r#type: "button",
126 class: "sd-alert__close",
127 onclick: move |e| close_handler.call(e),
128 Icon { kind: IconKind::X, size: 14 }
129 }
130 }
131 }
132 }
133}