htmx_components/server/
alert.rs1use rscx::{component, html, props};
2
3pub enum AlertKind {
4 Error,
5 Info,
6 Success,
7 Warning,
8}
9
10#[props]
11pub struct AlertProps {
12 #[builder(default=AlertKind::Error)]
13 kind: AlertKind,
14
15 #[builder(setter(into))]
16 title: String,
17
18 #[builder(setter(into), default)]
19 class: String,
20
21 #[builder(default)]
22 children: String,
23}
24
25#[component]
26pub fn Alert(props: AlertProps) -> String {
27 let (bg_color, title_color, description_color) = match props.kind {
28 AlertKind::Error => ("bg-red-50", "text-red-800", "text-red-700"),
29 AlertKind::Info => ("bg-blue-50", "text-blue-800", "text-blue-700"),
30 AlertKind::Warning => ("bg-yellow-50", "text-yellow-800", "text-yellow-700"),
31 AlertKind::Success => ("bg-green-50", "text-green-800", "text-green-700"),
32 };
33
34 html! {
35 <div class=format!("rounded-md {} p-4 {}", bg_color, props.class).trim()>
36 <div class="flex">
37 <div class="flex-shrink-0">
38 <AlertIcon kind=props.kind />
39 </div>
40 <div class="ml-3">
41 <h3 class=format!("text-sm font-medium {}", title_color)>{props.title}</h3>
42 {if !props.children.is_empty() {
43 html! {
44 <div class=format!("mt-2 text-sm {}", description_color)>{props.children}</div>
45 }
46 } else {
47 html! {
48 <></>
49 }
50 }}
51 </div>
52 </div>
53 </div>
54 }
55}
56
57#[component]
58fn AlertIcon(kind: AlertKind) -> String {
59 match kind {
60 AlertKind::Error => html! {
61 <svg class="h-5 w-5 text-red-400" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
62 <path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zM8.28 7.22a.75.75 0 00-1.06 1.06L8.94 10l-1.72 1.72a.75.75 0 101.06 1.06L10 11.06l1.72 1.72a.75.75 0 101.06-1.06L11.06 10l1.72-1.72a.75.75 0 00-1.06-1.06L10 8.94 8.28 7.22z" clip-rule="evenodd" />
63 </svg>
64 },
65 AlertKind::Info => html! {
66 <svg class="h-5 w-5 text-blue-400" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
67 <path fill-rule="evenodd" d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a.75.75 0 000 1.5h.253a.25.25 0 01.244.304l-.459 2.066A1.75 1.75 0 0010.747 15H11a.75.75 0 000-1.5h-.253a.25.25 0 01-.244-.304l.459-2.066A1.75 1.75 0 009.253 9H9z" clip-rule="evenodd" />
68 </svg>
69 },
70 AlertKind::Success => html! {
71 <svg class="h-5 w-5 text-green-400" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
72 <path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z" clip-rule="evenodd" />
73 </svg>
74 },
75 AlertKind::Warning => html! {
76 <svg class="h-5 w-5 text-yellow-400" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
77 <path fill-rule="evenodd" d="M8.485 2.495c.673-1.167 2.357-1.167 3.03 0l6.28 10.875c.673 1.167-.17 2.625-1.516 2.625H3.72c-1.347 0-2.189-1.458-1.515-2.625L8.485 2.495zM10 5a.75.75 0 01.75.75v3.5a.75.75 0 01-1.5 0v-3.5A.75.75 0 0110 5zm0 9a1 1 0 100-2 1 1 0 000 2z" clip-rule="evenodd" />
78 </svg>
79 },
80 }
81}