patternfly_yew/components/
alert.rs1use crate::ouia;
4use crate::prelude::wrap::wrapper_elt_with_attributes;
5use crate::prelude::{Action, Button, ButtonVariant, Icon};
6use crate::utils::{Ouia, OuiaComponentType, OuiaSafe};
7use yew::prelude::*;
8use yew::virtual_dom::ApplyAttributeAs;
9
10const OUIA: Ouia = ouia!("Alert");
11
12#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Ord, PartialOrd)]
13pub enum AlertType {
14 #[default]
15 Custom,
16 Info,
17 Success,
18 Warning,
19 Danger,
20}
21
22impl AlertType {
23 pub fn as_classes(&self) -> Vec<&'static str> {
24 match self {
25 AlertType::Custom => vec!["pf-m-custom"],
26 AlertType::Info => vec!["pf-m-info"],
27 AlertType::Success => vec!["pf-m-success"],
28 AlertType::Warning => vec!["pf-m-warning"],
29 AlertType::Danger => vec!["pf-m-danger"],
30 }
31 }
32
33 pub fn aria_label(&self) -> &'static str {
34 match self {
35 AlertType::Custom => "Custom alert",
36 AlertType::Info => "Information alert",
37 AlertType::Success => "Success alert",
38 AlertType::Warning => "Warning alert",
39 AlertType::Danger => "Danger alert",
40 }
41 }
42
43 pub fn icon(&self) -> Icon {
44 match self {
45 AlertType::Custom => Icon::Bell,
46 AlertType::Info => Icon::InfoCircle,
47 AlertType::Success => Icon::CheckCircle,
48 AlertType::Warning => Icon::ExclamationTriangle,
49 AlertType::Danger => Icon::ExclamationCircle,
50 }
51 }
52}
53
54#[derive(Clone, PartialEq, Properties)]
56pub struct AlertProperties {
57 #[prop_or_default]
58 pub id: String,
59 #[prop_or_default]
60 pub r#type: AlertType,
61 pub title: String,
62 #[prop_or_default]
63 pub children: Children,
64 #[prop_or_default]
65 pub inline: bool,
66 #[prop_or_default]
67 pub plain: bool,
68 #[prop_or_default]
69 pub truncate: bool,
70 #[prop_or_default]
71 pub actions: Vec<Action>,
72 #[prop_or_default]
73 pub onclose: Option<Callback<()>>,
74
75 #[prop_or_default]
77 pub ouia_id: Option<String>,
78 #[prop_or(OUIA.component_type())]
80 pub ouia_type: OuiaComponentType,
81 #[prop_or(OuiaSafe::TRUE)]
83 pub ouia_safe: OuiaSafe,
84}
85
86#[function_component(Alert)]
96pub fn alert(props: &AlertProperties) -> Html {
97 let ouia_id = use_memo(props.ouia_id.clone(), |id| {
98 id.clone().unwrap_or(OUIA.generated_id())
99 });
100 let mut classes = classes!("pf-v5-c-alert");
101
102 classes.extend(props.r#type.as_classes());
103
104 if props.inline {
105 classes.push("pf-m-inline");
106 }
107 if props.plain {
108 classes.push("pf-m-plain");
109 }
110
111 let mut title_classes = classes!("pf-v5-c-alert__title");
112
113 if props.truncate {
114 title_classes.push("pf-m-truncate");
115 }
116
117 let t = props.r#type;
118
119 let actions = if props.actions.is_empty() {
120 html!()
121 } else {
122 html! (
123 <div class="pf-v5-c-alert__action-group">
124 {for props.actions.iter().map(|action|{
125 html!{
126 <Button
127 variant={ButtonVariant::InlineLink}
128 label={action.label.clone()}
129 onclick={action.callback.reform(|_|())}
130 />
131 }
132 })}
133 </div>
134 )
135 };
136
137 html! (
138 <div
139 id={props.id.clone()}
140 class={classes}
141 aria_label={t.aria_label()}
142 data-ouia-component-id={(*ouia_id).clone()}
143 data-ouia-component-type={props.ouia_type}
144 data-ouia-safe={props.ouia_safe}
145 >
146 <div class="pf-v5-c-alert__icon">{ t.icon() }</div>
147 <p class={title_classes}>
148 <span class="pf-v5-screen-reader">{ t.aria_label() }{":"}</span>
149 { &props.title }
150 </p>
151
152
153 if let Some(onclose) = props.onclose.as_ref() {
154 <div class="pf-v5-c-alert__action">
155 <Button variant={ButtonVariant::Plain} icon={Icon::Times} onclick={onclose.clone().reform(|_|())} />
156 </div>
157 }
158
159
160 if !props.children.is_empty() {
161 <div class="pf-v5-c-alert__description">
162 { props.children.clone() }
163 </div>
164 }
165
166 { actions }
167
168 </div>
169 )
170}
171
172#[derive(Clone, PartialEq, Properties)]
176pub struct GroupProperties {
177 #[prop_or_default]
178 pub children: ChildrenWithProps<Alert>,
179 #[prop_or_default]
180 pub toast: bool,
181}
182
183#[function_component(AlertGroup)]
184pub fn view(props: &GroupProperties) -> Html {
185 let mut classes = classes!("pf-v5-c-alert-group");
186
187 if props.toast {
188 classes.push(classes!("pf-m-toast"));
189 }
190
191 html! (
192 <ul class={classes} role="list">
193 { for props.children.iter().map(|child|
194 wrapper_elt_with_attributes(child.to_html(), "li", &[("class", "pf-v5-c-alert-group__item", ApplyAttributeAs::Attribute)])
195 )}
196 </ul>
197 )
198}