Detailed changes
@@ -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")]
@@ -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 {
@@ -0,0 +1,71 @@
+use ui::{prelude::*, Avatar, IconButtonShape};
+
+#[derive(IntoElement)]
+pub struct ChatNotice {
+ message: SharedString,
+ meta: Option<SharedString>,
+}
+
+impl ChatNotice {
+ pub fn new(message: impl Into<SharedString>) -> Self {
+ Self {
+ message: message.into(),
+ meta: None,
+ }
+ }
+
+ pub fn meta(mut self, meta: impl Into<SharedString>) -> 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)
+ }),
+ ),
+ )
+ }
+}
@@ -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();
}
@@ -1,3 +1,5 @@
mod chat_message;
+mod chat_notice;
pub use chat_message::*;
+pub use chat_notice::*;
@@ -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<Self>) -> 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."),
+ )),
+ )
+ }
+}
@@ -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(),