a3s-tui 0.1.4

TEA (The Elm Architecture) framework for terminal user interfaces
Documentation
use crate::element::{BorderStyle, BoxElement, Element, FlexDirection, TextElement};
use crate::style::Color;

#[derive(Debug, Clone, Copy)]
pub enum AlertKind {
    Info,
    Success,
    Warning,
    Error,
}

pub struct Alert {
    kind: AlertKind,
    title: String,
    body: String,
}

impl Alert {
    pub fn new(kind: AlertKind, body: impl Into<String>) -> Self {
        Self {
            kind,
            title: String::new(),
            body: body.into(),
        }
    }

    pub fn title(mut self, t: impl Into<String>) -> Self {
        self.title = t.into();
        self
    }

    pub fn element<Msg>(&self) -> Element<Msg> {
        let (icon, color) = match self.kind {
            AlertKind::Info => ("", Color::Blue),
            AlertKind::Success => ("", Color::Green),
            AlertKind::Warning => ("", Color::Yellow),
            AlertKind::Error => ("", Color::Red),
        };

        let mut children: Vec<Element<Msg>> = Vec::new();

        if !self.title.is_empty() {
            children.push(Element::Text(
                TextElement::new(format!("{} {}", icon, self.title))
                    .bold()
                    .fg(color),
            ));
        } else {
            children.push(Element::Text(TextElement::new(icon).bold().fg(color)));
        }

        children.push(Element::Text(TextElement::new(&self.body)));

        Element::Box(
            BoxElement::new()
                .direction(FlexDirection::Column)
                .border(BorderStyle::Rounded)
                .border_color(color)
                .padding(1)
                .children(children),
        )
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn alert_without_title() {
        let alert = Alert::new(AlertKind::Info, "message");
        let el: Element<()> = alert.element();
        match el {
            Element::Box(b) => assert_eq!(b.children.len(), 2),
            _ => panic!("expected Box"),
        }
    }

    #[test]
    fn alert_with_title() {
        let alert = Alert::new(AlertKind::Success, "done").title("Status");
        let el: Element<()> = alert.element();
        match el {
            Element::Box(b) => assert_eq!(b.children.len(), 2),
            _ => panic!("expected Box"),
        }
    }

    #[test]
    fn alert_kinds() {
        for kind in [
            AlertKind::Info,
            AlertKind::Success,
            AlertKind::Warning,
            AlertKind::Error,
        ] {
            let alert = Alert::new(kind, "test");
            let _el: Element<()> = alert.element();
        }
    }
}