diff --git a/crates/agent_ui/src/ui.rs b/crates/agent_ui/src/ui.rs index b484fdb6c6c480f1cffe78eea7a51f635d3906a1..376c50ef483d3cea37ac7d841093d6e6b7a19d07 100644 --- a/crates/agent_ui/src/ui.rs +++ b/crates/agent_ui/src/ui.rs @@ -4,6 +4,7 @@ mod burn_mode_tooltip; mod claude_code_onboarding_modal; mod end_trial_upsell; mod hold_for_default; +mod mention_crease; mod model_selector_components; mod onboarding_modal; mod usage_callout; @@ -14,6 +15,7 @@ pub use burn_mode_tooltip::*; pub use claude_code_onboarding_modal::*; pub use end_trial_upsell::*; pub use hold_for_default::*; +pub use mention_crease::*; pub use model_selector_components::*; pub use onboarding_modal::*; pub use usage_callout::*; diff --git a/crates/agent_ui/src/ui/mention_crease.rs b/crates/agent_ui/src/ui/mention_crease.rs new file mode 100644 index 0000000000000000000000000000000000000000..215bab2be80c7f68d00f361da3b4c50364dd1cc2 --- /dev/null +++ b/crates/agent_ui/src/ui/mention_crease.rs @@ -0,0 +1,99 @@ +use std::time::Duration; + +use gpui::{Animation, AnimationExt, AnyView, IntoElement, Window, pulsating_between}; +use settings::Settings; +use theme::ThemeSettings; +use ui::{ButtonLike, TintColor, prelude::*}; + +#[derive(IntoElement)] +pub struct MentionCrease { + id: ElementId, + icon: SharedString, + label: SharedString, + is_toggled: bool, + is_loading: bool, + image_preview: Option AnyView + 'static>>, +} + +impl MentionCrease { + pub fn new( + id: impl Into, + icon: impl Into, + label: impl Into, + ) -> Self { + Self { + id: id.into(), + icon: icon.into(), + label: label.into(), + is_toggled: false, + is_loading: false, + image_preview: None, + } + } + + pub fn is_toggled(mut self, is_toggled: bool) -> Self { + self.is_toggled = is_toggled; + self + } + + pub fn is_loading(mut self, is_loading: bool) -> Self { + self.is_loading = is_loading; + self + } + + pub fn image_preview( + mut self, + builder: impl Fn(&mut Window, &mut App) -> AnyView + 'static, + ) -> Self { + self.image_preview = Some(Box::new(builder)); + self + } +} + +impl RenderOnce for MentionCrease { + fn render(self, window: &mut Window, cx: &mut App) -> impl IntoElement { + let settings = ThemeSettings::get_global(cx); + let font_size = settings.agent_buffer_font_size(cx); + let buffer_font = settings.buffer_font.clone(); + + let button_height = DefiniteLength::Absolute(AbsoluteLength::Pixels( + px(window.line_height().into()) - px(2.), + )); + + ButtonLike::new(self.id) + .style(ButtonStyle::Outlined) + .size(ButtonSize::Compact) + .height(button_height) + .selected_style(ButtonStyle::Tinted(TintColor::Accent)) + .toggle_state(self.is_toggled) + .when_some(self.image_preview, |this, image_preview| { + this.hoverable_tooltip(image_preview) + }) + .child( + h_flex() + .gap_1() + .font(buffer_font) + .text_size(font_size) + .child( + Icon::from_path(self.icon.clone()) + .size(IconSize::XSmall) + .color(Color::Muted), + ) + .child(self.label.clone()) + .map(|this| { + if self.is_loading { + this.with_animation( + "loading-context-crease", + Animation::new(Duration::from_secs(2)) + .repeat() + .with_easing(pulsating_between(0.4, 0.8)), + |label, delta| label.opacity(delta), + ) + .into_any() + } else { + this.into_any() + } + }), + ) + } +}