From 3dc5d48e0cffec2f2c401e7042e7fee4acd0ea37 Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Wed, 1 May 2024 14:51:28 -0400 Subject: [PATCH] assistant2: Add `ChatNotice` component (#11262) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR adds a new `ChatNotice` component for displaying notices within the assistant. We will be able to use this for allowing the user to confirm a project index request. Screenshot 2024-05-01 at 2 41 31 PM Release Notes: - N/A --- crates/assistant2/src/ui.rs | 2 + crates/assistant2/src/ui/chat_message.rs | 2 +- crates/assistant2/src/ui/chat_notice.rs | 71 +++++++++++++++++++ crates/assistant2/src/ui/composer.rs | 4 +- crates/assistant2/src/ui/stories.rs | 2 + .../assistant2/src/ui/stories/chat_notice.rs | 22 ++++++ crates/storybook/src/story_selector.rs | 2 + 7 files changed, 102 insertions(+), 3 deletions(-) create mode 100644 crates/assistant2/src/ui/chat_notice.rs create mode 100644 crates/assistant2/src/ui/stories/chat_notice.rs diff --git a/crates/assistant2/src/ui.rs b/crates/assistant2/src/ui.rs index cfe0e7bf24..25b367949e 100644 --- a/crates/assistant2/src/ui.rs +++ b/crates/assistant2/src/ui.rs @@ -1,10 +1,12 @@ mod chat_message; +mod chat_notice; mod composer; #[cfg(feature = "stories")] mod stories; pub use chat_message::*; +pub use chat_notice::*; pub use composer::*; #[cfg(feature = "stories")] diff --git a/crates/assistant2/src/ui/chat_message.rs b/crates/assistant2/src/ui/chat_message.rs index 816515d417..ab26979897 100644 --- a/crates/assistant2/src/ui/chat_message.rs +++ b/crates/assistant2/src/ui/chat_message.rs @@ -118,7 +118,7 @@ impl RenderOnce for ChatMessageHeader { h_flex() .gap_3() .map(|this| { - let avatar_size = rems(20.0 / 16.0); + let avatar_size = rems_from_px(20.); if let Some(avatar_uri) = avatar_uri { this.child(Avatar::new(avatar_uri).size(avatar_size)) } else { diff --git a/crates/assistant2/src/ui/chat_notice.rs b/crates/assistant2/src/ui/chat_notice.rs new file mode 100644 index 0000000000..5001d2d23e --- /dev/null +++ b/crates/assistant2/src/ui/chat_notice.rs @@ -0,0 +1,71 @@ +use ui::{prelude::*, Avatar, IconButtonShape}; + +#[derive(IntoElement)] +pub struct ChatNotice { + message: SharedString, + meta: Option, +} + +impl ChatNotice { + pub fn new(message: impl Into) -> Self { + Self { + message: message.into(), + meta: None, + } + } + + pub fn meta(mut self, meta: impl Into) -> Self { + self.meta = Some(meta.into()); + self + } +} + +impl RenderOnce for ChatNotice { + fn render(self, _cx: &mut WindowContext) -> impl IntoElement { + h_flex() + .w_full() + .items_start() + .mt_4() + .gap_3() + .child( + // TODO: Replace with question mark. + Avatar::new("https://zed.dev/assistant_avatar.png").size(rems_from_px(20.)), + ) + .child( + v_flex() + .size_full() + .gap_1() + .pr_4() + .overflow_hidden() + .child( + h_flex() + .justify_between() + .overflow_hidden() + .child( + h_flex() + .flex_none() + .overflow_hidden() + .child(Label::new(self.message)), + ) + .child( + h_flex() + .flex_shrink_0() + .gap_1() + .child(Button::new("allow", "Allow")) + .child( + IconButton::new("deny", IconName::Close) + .shape(IconButtonShape::Square) + .icon_color(Color::Muted) + .size(ButtonSize::None) + .icon_size(IconSize::XSmall), + ), + ), + ) + .children( + self.meta.map(|meta| { + Label::new(meta).size(LabelSize::Small).color(Color::Muted) + }), + ), + ) + } +} diff --git a/crates/assistant2/src/ui/composer.rs b/crates/assistant2/src/ui/composer.rs index a0da37f21f..7e07be4c30 100644 --- a/crates/assistant2/src/ui/composer.rs +++ b/crates/assistant2/src/ui/composer.rs @@ -38,10 +38,10 @@ impl Composer { impl RenderOnce for Composer { fn render(self, cx: &mut WindowContext) -> impl IntoElement { - let mut player_avatar = div().size(rems(20.0 / 16.0)).into_any_element(); + let mut player_avatar = div().size(rems_from_px(20.)).into_any_element(); if let Some(player) = self.player.clone() { player_avatar = Avatar::new(player.avatar_uri.clone()) - .size(rems(20.0 / 16.0)) + .size(rems_from_px(20.)) .into_any_element(); } diff --git a/crates/assistant2/src/ui/stories.rs b/crates/assistant2/src/ui/stories.rs index 2aca1f0676..8bc2b30d66 100644 --- a/crates/assistant2/src/ui/stories.rs +++ b/crates/assistant2/src/ui/stories.rs @@ -1,3 +1,5 @@ mod chat_message; +mod chat_notice; pub use chat_message::*; +pub use chat_notice::*; diff --git a/crates/assistant2/src/ui/stories/chat_notice.rs b/crates/assistant2/src/ui/stories/chat_notice.rs new file mode 100644 index 0000000000..ad8eef92c7 --- /dev/null +++ b/crates/assistant2/src/ui/stories/chat_notice.rs @@ -0,0 +1,22 @@ +use story::{StoryContainer, StoryItem, StorySection}; +use ui::prelude::*; + +use crate::ui::ChatNotice; + +pub struct ChatNoticeStory; + +impl Render for ChatNoticeStory { + fn render(&mut self, _cx: &mut ViewContext) -> impl IntoElement { + StoryContainer::new( + "ChatNotice Story", + "crates/assistant2/src/ui/stories/chat_notice.rs", + ) + .child( + StorySection::new().child(StoryItem::new( + "Project index request", + ChatNotice::new("Allow assistant to index your project?") + .meta("Enabling will allow responses more relevant to this project."), + )), + ) + } +} diff --git a/crates/storybook/src/story_selector.rs b/crates/storybook/src/story_selector.rs index 5087295ca9..b4b20b9087 100644 --- a/crates/storybook/src/story_selector.rs +++ b/crates/storybook/src/story_selector.rs @@ -13,6 +13,7 @@ use ui::prelude::*; #[strum(serialize_all = "snake_case")] pub enum ComponentStory { AssistantChatMessage, + AssistantChatNotice, AutoHeightEditor, Avatar, Button, @@ -46,6 +47,7 @@ impl ComponentStory { Self::AssistantChatMessage => { cx.new_view(|_cx| assistant2::ui::ChatMessageStory).into() } + Self::AssistantChatNotice => cx.new_view(|_cx| assistant2::ui::ChatNoticeStory).into(), Self::AutoHeightEditor => AutoHeightEditorStory::new(cx).into(), Self::Avatar => cx.new_view(|_| ui::AvatarStory).into(), Self::Button => cx.new_view(|_| ui::ButtonStory).into(),