agent: Add UI for upsell scenarios (#29805)

Release Notes:

- N/A

---------

Co-authored-by: Marshall Bowers <git@maxdeviant.com>
This commit is contained in:
Nate Butler 2025-05-04 20:48:06 -04:00 committed by GitHub
parent a19687a815
commit fe177f5d69
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
13 changed files with 659 additions and 135 deletions

View file

@ -1,6 +1,7 @@
mod avatar;
mod banner;
mod button;
mod callout;
mod content_group;
mod context_menu;
mod disclosure;
@ -41,6 +42,7 @@ mod stories;
pub use avatar::*;
pub use banner::*;
pub use button::*;
pub use callout::*;
pub use content_group::*;
pub use context_menu::*;
pub use disclosure::*;

View file

@ -0,0 +1,162 @@
use crate::prelude::*;
use gpui::ClickEvent;
#[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: SharedString,
icon: Icon,
cta_label: SharedString,
cta_action: Box<dyn Fn(&ClickEvent, &mut Window, &mut App) + 'static>,
) -> Self {
Self {
title,
message: None,
icon,
cta_label,
cta_action,
line_height: None,
}
}
pub fn multi_line(
title: SharedString,
message: SharedString,
icon: Icon,
cta_label: SharedString,
cta_action: Box<dyn Fn(&ClickEvent, &mut Window, &mut App) + 'static>,
) -> Self {
Self {
title,
message: Some(message),
icon,
cta_label,
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.".into(),
Icon::new(IconName::Warning)
.color(Color::Warning)
.size(IconSize::Small),
"Backup & Update".into(),
Box::new(|_, _, _| {}),
)
.into_any_element(),
)
.width(px(580.)),
single_example(
"Multi Line",
Callout::multi_line(
"Thread reached the token limit".into(),
"Start a new thread from a summary to continue the conversation.".into(),
Icon::new(IconName::X)
.color(Color::Error)
.size(IconSize::Small),
"Start New Thread".into(),
Box::new(|_, _, _| {}),
)
.into_any_element(),
)
.width(px(580.)),
];
Some(
example_group(callout_examples)
.vertical()
.into_any_element(),
)
}
}