188 lines · 6.0 KB · Rust
RawDownload
use crate::prelude::*;use gpui::{AnyElement, IntoElement, ParentElement, Styled}; /// Banners provide informative and brief messages without interrupting the user./// This component offers four severity levels that can be used depending on the message.////// # Usage Example////// ```/// use ui::prelude::*;/// use ui::{Banner, Button, Icon, IconName, IconSize, Label, Severity};////// Banner::new()///     .severity(Severity::Success)///     .children([Label::new("This is a success message")])///     .action_slot(///         Button::new("learn-more", "Learn More")///             .end_icon(Icon::new(IconName::ArrowUpRight).size(IconSize::Small)),///     );/// ```#[derive(IntoElement, RegisterComponent)]pub struct Banner {    severity: Severity,    children: Vec<AnyElement>,    action_slot: Option<AnyElement>,    wrap_content: bool,} impl Banner {    /// Creates a new `Banner` component with default styling.    pub fn new() -> Self {        Self {            severity: Severity::Info,            children: Vec::new(),            action_slot: None,            wrap_content: false,        }    }     /// Sets the severity of the banner.    pub fn severity(mut self, severity: Severity) -> Self {        self.severity = severity;        self    }     /// A slot for actions, such as CTA or dismissal buttons.    pub fn action_slot(mut self, element: impl IntoElement) -> Self {        self.action_slot = Some(element.into_any_element());        self    }     /// Sets whether the banner content should wrap.    pub fn wrap_content(mut self, wrap: bool) -> Self {        self.wrap_content = wrap;        self    }} impl ParentElement for Banner {    fn extend(&mut self, elements: impl IntoIterator<Item = AnyElement>) {        self.children.extend(elements)    }} impl RenderOnce for Banner {    fn render(self, window: &mut Window, cx: &mut App) -> impl IntoElement {        let banner = h_flex()            .min_w_0()            .py_0p5()            .gap_1p5()            .when(self.wrap_content, |this| this.flex_wrap())            .justify_between()            .rounded_sm()            .border_1();         let (icon, icon_color, bg_color, border_color) = match self.severity {            Severity::Info => (                IconName::Info,                Color::Muted,                cx.theme().status().info_background.opacity(0.5),                cx.theme().colors().border.opacity(0.5),            ),            Severity::Success => (                IconName::Check,                Color::Success,                cx.theme().status().success.opacity(0.1),                cx.theme().status().success.opacity(0.2),            ),            Severity::Warning => (                IconName::Warning,                Color::Warning,                cx.theme().status().warning_background.opacity(0.5),                cx.theme().status().warning_border.opacity(0.4),            ),            Severity::Error => (                IconName::XCircle,                Color::Error,                cx.theme().status().error.opacity(0.1),                cx.theme().status().error.opacity(0.2),            ),        };         let mut banner = banner.bg(bg_color).border_color(border_color);         let icon_and_child = h_flex()            .items_start()            .min_w_0()            .flex_1()            .gap_1p5()            .child(                h_flex()                    .h(window.line_height())                    .flex_shrink_0()                    .child(Icon::new(icon).size(IconSize::XSmall).color(icon_color)),            )            .child(div().min_w_0().flex_1().children(self.children));         if let Some(action_slot) = self.action_slot {            banner = banner                .pl_2()                .pr_1()                .child(icon_and_child)                .child(action_slot);        } else {            banner = banner.px_2().child(icon_and_child);        }         banner    }} impl Component for Banner {    fn scope() -> ComponentScope {        ComponentScope::DataDisplay    }     fn preview(_window: &mut Window, _cx: &mut App) -> Option<AnyElement> {        let severity_examples = vec![            single_example(                "Default",                Banner::new()                    .child(Label::new("This is a default banner with no customization"))                    .into_any_element(),            ),            single_example(                "Info",                Banner::new()                    .severity(Severity::Info)                    .child(Label::new("This is an informational message"))                    .action_slot(                        Button::new("learn-more", "Learn More")                            .end_icon(Icon::new(IconName::ArrowUpRight).size(IconSize::Small)),                    )                    .into_any_element(),            ),            single_example(                "Success",                Banner::new()                    .severity(Severity::Success)                    .child(Label::new("Operation completed successfully"))                    .action_slot(Button::new("dismiss", "Dismiss"))                    .into_any_element(),            ),            single_example(                "Warning",                Banner::new()                    .severity(Severity::Warning)                    .child(Label::new("Your settings file uses deprecated settings"))                    .action_slot(Button::new("update", "Update Settings"))                    .into_any_element(),            ),            single_example(                "Error",                Banner::new()                    .severity(Severity::Error)                    .child(Label::new("Connection error: unable to connect to server"))                    .action_slot(Button::new("reconnect", "Retry"))                    .into_any_element(),            ),        ];         Some(            example_group(severity_examples)                .vertical()                .into_any_element(),        )    }}

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t