use crate::ouia;
use crate::prelude::{Action, Button, ButtonVariant, Icon};
use crate::utils::{Ouia, OuiaComponentType, OuiaSafe};
use yew::prelude::*;
const OUIA: Ouia = ouia!("Alert");
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Ord, PartialOrd)]
pub enum AlertType {
#[default]
Custom,
Info,
Success,
Warning,
Danger,
}
impl AlertType {
pub fn as_classes(&self) -> Vec<&'static str> {
match self {
AlertType::Custom => vec!["pf-m-custom"],
AlertType::Info => vec!["pf-m-info"],
AlertType::Success => vec!["pf-m-success"],
AlertType::Warning => vec!["pf-m-warning"],
AlertType::Danger => vec!["pf-m-danger"],
}
}
pub fn aria_label(&self) -> &'static str {
match self {
AlertType::Custom => "Custom alert",
AlertType::Info => "Information alert",
AlertType::Success => "Success alert",
AlertType::Warning => "Warning alert",
AlertType::Danger => "Danger alert",
}
}
pub fn icon(&self) -> Icon {
match self {
AlertType::Custom => Icon::Bell,
AlertType::Info => Icon::InfoCircle,
AlertType::Success => Icon::CheckCircle,
AlertType::Warning => Icon::ExclamationTriangle,
AlertType::Danger => Icon::ExclamationCircle,
}
}
}
#[derive(Clone, PartialEq, Properties)]
pub struct AlertProperties {
#[prop_or_default]
pub id: String,
#[prop_or_default]
pub r#type: AlertType,
pub title: String,
#[prop_or_default]
pub children: Children,
#[prop_or_default]
pub inline: bool,
#[prop_or_default]
pub plain: bool,
#[prop_or_default]
pub truncate: bool,
#[prop_or_default]
pub actions: Vec<Action>,
#[prop_or_default]
pub onclose: Option<Callback<()>>,
#[prop_or_default]
pub ouia_id: Option<String>,
#[prop_or(OUIA.component_type())]
pub ouia_type: OuiaComponentType,
#[prop_or(OuiaSafe::TRUE)]
pub ouia_safe: OuiaSafe,
}
#[function_component(Alert)]
pub fn alert(props: &AlertProperties) -> Html {
let ouia_id = use_memo(props.ouia_id.clone(), |id| {
id.clone().unwrap_or(OUIA.generated_id())
});
let mut classes = classes!("pf-v5-c-alert");
classes.extend(props.r#type.as_classes());
if props.inline {
classes.push("pf-m-inline");
}
if props.plain {
classes.push("pf-m-plain");
}
let mut title_classes = classes!("pf-v5-c-alert__title");
if props.truncate {
title_classes.push("pf-m-truncate");
}
let t = props.r#type;
let actions = if props.actions.is_empty() {
html!()
} else {
html! (
<div class="pf-v5-c-alert__action-group">
{for props.actions.iter().map(|action|{
html!{
<Button
variant={ButtonVariant::InlineLink}
label={action.label.clone()}
onclick={action.callback.reform(|_|())}
/>
}
})}
</div>
)
};
html! (
<div
id={props.id.clone()}
class={classes}
aria_label={t.aria_label()}
data-ouia-component-id={(*ouia_id).clone()}
data-ouia-component-type={props.ouia_type}
data-ouia-safe={props.ouia_safe}
>
<div class="pf-v5-c-alert__icon">{ t.icon() }</div>
<p class={title_classes}>
<span class="pf-v5-screen-reader">{ t.aria_label() }{":"}</span>
{ &props.title }
</p>
if let Some(onclose) = props.onclose.as_ref() {
<div class="pf-v5-c-alert__action">
<Button variant={ButtonVariant::Plain} icon={Icon::Times} onclick={onclose.clone().reform(|_|())} />
</div>
}
if !props.children.is_empty() {
<div class="pf-v5-c-alert__description">
{ props.children.clone() }
</div>
}
{ actions }
</div>
)
}
#[derive(Clone, PartialEq, Properties)]
pub struct GroupProperties {
#[prop_or_default]
pub children: ChildrenWithProps<Alert>,
#[prop_or_default]
pub toast: bool,
}
#[function_component(AlertGroup)]
pub fn view(props: &GroupProperties) -> Html {
let mut classes = classes!("pf-v5-c-alert-group");
if props.toast {
classes.push(classes!("pf-m-toast"));
}
html! (
<ul class={classes} role="list">
{ for props.children.iter().map(|child|html!{
<li class="pf-v5-c-alert-group__item">
{ child }
</li>
})}
</ul>
)
}