163 lines · 5.3 KB · Rust
RawDownload
use gpui::ClickEvent; use crate::prelude::*; #[derive(IntoElement, RegisterComponent)]pub struct Callout {    title: SharedString,    message: Option<SharedString>,    icon: Icon,    cta_label: SharedString,    cta_action: Box<dyn Fn(&ClickEvent, &mut Window, &mut App) + 'static>,    line_height: Option<Pixels>,} impl Callout {    pub fn single_line(        title: impl Into<SharedString>,        icon: Icon,        cta_label: impl Into<SharedString>,        cta_action: Box<dyn Fn(&ClickEvent, &mut Window, &mut App) + 'static>,    ) -> Self {        Self {            title: title.into(),            message: None,            icon,            cta_label: cta_label.into(),            cta_action,            line_height: None,        }    }     pub fn multi_line(        title: impl Into<SharedString>,        message: impl Into<SharedString>,        icon: Icon,        cta_label: impl Into<SharedString>,        cta_action: Box<dyn Fn(&ClickEvent, &mut Window, &mut App) + 'static>,    ) -> Self {        Self {            title: title.into(),            message: Some(message.into()),            icon,            cta_label: cta_label.into(),            cta_action,            line_height: None,        }    }     pub fn line_height(mut self, line_height: Pixels) -> Self {        self.line_height = Some(line_height);        self    }} impl RenderOnce for Callout {    fn render(self, window: &mut Window, cx: &mut App) -> impl IntoElement {        let line_height = self.line_height.unwrap_or(window.line_height());         h_flex()            .p_2()            .gap_2()            .w_full()            .items_center()            .justify_between()            .bg(cx.theme().colors().panel_background)            .border_t_1()            .border_color(cx.theme().colors().border)            .overflow_x_hidden()            .child(                h_flex()                    .flex_shrink()                    .overflow_hidden()                    .gap_2()                    .items_start()                    .child(                        h_flex()                            .h(line_height)                            .items_center()                            .justify_center()                            .child(self.icon),                    )                    .child(                        v_flex()                            .flex_shrink()                            .overflow_hidden()                            .child(                                h_flex()                                    .h(line_height)                                    .items_center()                                    .child(Label::new(self.title).size(LabelSize::Small)),                            )                            .when_some(self.message, |this, message| {                                this.child(                                    div()                                        .w_full()                                        .flex_1()                                        .child(message)                                        .text_ui_sm(cx)                                        .text_color(cx.theme().colors().text_muted),                                )                            }),                    ),            )            .child(                div().flex_none().child(                    Button::new("cta", self.cta_label)                        .on_click(self.cta_action)                        .style(ButtonStyle::Filled)                        .label_size(LabelSize::Small),                ),            )    }} impl Component for Callout {    fn scope() -> ComponentScope {        ComponentScope::Notification    }     fn description() -> Option<&'static str> {        Some(            "Used to display a callout for situations where the user needs to know some information, and likely make a decision. This might be a thread running out of tokens, or running out of prompts on a plan and needing to upgrade.",        )    }     fn preview(_window: &mut Window, _cx: &mut App) -> Option<AnyElement> {        let callout_examples = vec![            single_example(                "Single Line",                Callout::single_line(                    "Your settings contain deprecated values, please update them.",                    Icon::new(IconName::Warning)                        .color(Color::Warning)                        .size(IconSize::Small),                    "Backup & Update",                    Box::new(|_, _, _| {}),                )                .into_any_element(),            )            .width(px(580.)),            single_example(                "Multi Line",                Callout::multi_line(                    "Thread reached the token limit",                    "Start a new thread from a summary to continue the conversation.",                    Icon::new(IconName::X)                        .color(Color::Error)                        .size(IconSize::Small),                    "Start New Thread",                    Box::new(|_, _, _| {}),                )                .into_any_element(),            )            .width(px(580.)),        ];         Some(            example_group(callout_examples)                .vertical()                .into_any_element(),        )    }}