assistant2: Add stray visual adjustments (#22111)

Mostly minor tweaks to make it closer to the prototype. More to come.

| With message | Empty state |
|--------|--------|
| <img width="1420" alt="Screenshot 2024-12-16 at 18 59 40"
src="https://github.com/user-attachments/assets/5df791bf-577a-4f01-9045-80568604099f"
/> | <img width="1420" alt="Screenshot 2024-12-16 at 18 59 33"
src="https://github.com/user-attachments/assets/adbf1673-3040-4b2b-8d65-f8b38a83c1d0"
/> |

Release Notes:

- N/A
This commit is contained in:
Danilo Leal 2024-12-16 19:23:42 -03:00 committed by GitHub
parent 92fb38acb6
commit 53c8b48647
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 74 additions and 89 deletions

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-message-circle-more"><path d="M7.9 20A9 9 0 1 0 4 16.1L2 22Z"/><path d="M8 12h.01"/><path d="M12 12h.01"/><path d="M16 12h.01"/></svg>

After

Width:  |  Height:  |  Size: 337 B

View file

@ -1,3 +1,4 @@
<svg width="15" height="15" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M7.5 0.875C5.49797 0.875 3.875 2.49797 3.875 4.5C3.875 6.15288 4.98124 7.54738 6.49373 7.98351C5.2997 8.12901 4.27557 8.55134 3.50407 9.31167C2.52216 10.2794 2.02502 11.72 2.02502 13.5999C2.02502 13.8623 2.23769 14.0749 2.50002 14.0749C2.76236 14.0749 2.97502 13.8623 2.97502 13.5999C2.97502 11.8799 3.42786 10.7206 4.17091 9.9883C4.91536 9.25463 6.02674 8.87499 7.49995 8.87499C8.97317 8.87499 10.0846 9.25463 10.8291 9.98831C11.5721 10.7206 12.025 11.8799 12.025 13.5999C12.025 13.8623 12.2376 14.0749 12.5 14.0749C12.7623 14.075 12.975 13.8623 12.975 13.6C12.975 11.72 12.4778 10.2794 11.4959 9.31166C10.7244 8.55135 9.70025 8.12903 8.50625 7.98352C10.0187 7.5474 11.125 6.15289 11.125 4.5C11.125 2.49797 9.50203 0.875 7.5 0.875ZM4.825 4.5C4.825 3.02264 6.02264 1.825 7.5 1.825C8.97736 1.825 10.175 3.02264 10.175 4.5C10.175 5.97736 8.97736 7.175 7.5 7.175C6.02264 7.175 4.825 5.97736 4.825 4.5Z" fill="black"/>
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M12.6666 14V12.6667C12.6666 11.9594 12.3856 11.2811 11.8855 10.781C11.3854 10.281 10.7072 10 9.99992 10H5.99992C5.29267 10 4.6144 10.281 4.1143 10.781C3.6142 11.2811 3.33325 11.9594 3.33325 12.6667V14" stroke="black" stroke-width="1.33333" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M7.99992 7.33333C9.47268 7.33333 10.6666 6.13943 10.6666 4.66667C10.6666 3.19391 9.47268 2 7.99992 2C6.52716 2 5.33325 3.19391 5.33325 4.66667C5.33325 6.13943 6.52716 7.33333 7.99992 7.33333Z" stroke="black" stroke-width="1.33333" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

Before

Width:  |  Height:  |  Size: 1 KiB

After

Width:  |  Height:  |  Size: 690 B

Before After
Before After

View file

@ -213,26 +213,33 @@ impl ActiveThread {
div()
.id(("message-container", ix))
.p_2()
.py_1()
.px_2()
.child(
v_flex()
.border_1()
.border_color(cx.theme().colors().border_variant)
.border_color(cx.theme().colors().border)
.bg(cx.theme().colors().editor_background)
.rounded_md()
.child(
h_flex()
.justify_between()
.p_1p5()
.py_1()
.px_2()
.border_b_1()
.border_color(cx.theme().colors().border_variant)
.child(
h_flex()
.gap_2()
.child(Icon::new(role_icon).size(IconSize::Small))
.child(Label::new(role_name).size(LabelSize::Small)),
.gap_1p5()
.child(
Icon::new(role_icon)
.size(IconSize::XSmall)
.color(Color::Muted),
)
.child(Label::new(role_name).size(LabelSize::XSmall)),
),
)
.child(v_flex().p_1p5().text_ui(cx).child(markdown.clone()))
.child(v_flex().px_2().py_1().text_ui(cx).child(markdown.clone()))
.when_some(context, |parent, context| {
parent.child(
h_flex().flex_wrap().gap_2().p_1p5().children(
@ -249,6 +256,6 @@ impl ActiveThread {
impl Render for ActiveThread {
fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
list(self.list_state.clone()).flex_1()
list(self.list_state.clone()).flex_1().py_1()
}
}

View file

@ -10,7 +10,7 @@ use gpui::{
};
use language::LanguageRegistry;
use time::UtcOffset;
use ui::{prelude::*, Divider, IconButtonShape, KeyBinding, Tab, Tooltip};
use ui::{prelude::*, KeyBinding, Tab, Tooltip};
use workspace::dock::{DockPosition, Panel, PanelEvent};
use workspace::Workspace;
@ -202,7 +202,7 @@ impl Panel for AssistantPanel {
fn set_position(&mut self, _position: DockPosition, _cx: &mut ViewContext<Self>) {}
fn size(&self, _cx: &WindowContext) -> Pixels {
px(640.)
px(550.)
}
fn set_size(&mut self, _size: Option<Pixels>, _cx: &mut ViewContext<Self>) {}
@ -238,15 +238,17 @@ impl AssistantPanel {
.px(DynamicSpacing::Base08.rems(cx))
.bg(cx.theme().colors().tab_bar_background)
.border_b_1()
.border_color(cx.theme().colors().border_variant)
.border_color(cx.theme().colors().border)
.child(h_flex().children(self.thread.read(cx).summary(cx).map(Label::new)))
.child(
h_flex()
.gap(DynamicSpacing::Base08.rems(cx))
.child(Divider::vertical())
.h_full()
.pl_1()
.border_l_1()
.border_color(cx.theme().colors().border)
.gap(DynamicSpacing::Base02.rems(cx))
.child(
IconButton::new("new-thread", IconName::Plus)
.shape(IconButtonShape::Square)
.icon_size(IconSize::Small)
.style(ButtonStyle::Subtle)
.tooltip({
@ -266,7 +268,6 @@ impl AssistantPanel {
)
.child(
IconButton::new("open-history", IconName::HistoryRerun)
.shape(IconButtonShape::Square)
.icon_size(IconSize::Small)
.style(ButtonStyle::Subtle)
.tooltip({
@ -286,7 +287,6 @@ impl AssistantPanel {
)
.child(
IconButton::new("configure-assistant", IconName::Settings)
.shape(IconButtonShape::Square)
.icon_size(IconSize::Small)
.style(ButtonStyle::Subtle)
.tooltip(move |cx| Tooltip::text("Configure Assistant", cx))
@ -312,7 +312,6 @@ impl AssistantPanel {
v_flex()
.gap_2()
.mx_auto()
.child(
v_flex().w_full().child(
svg()
@ -334,7 +333,7 @@ impl AssistantPanel {
),
)
.child(
v_flex().gap_2().children(
v_flex().mx_auto().w_4_5().gap_2().children(
recent_threads
.into_iter()
.map(|thread| PastThread::new(thread, cx.view().downgrade())),
@ -541,7 +540,7 @@ impl Render for AssistantPanel {
.child(
h_flex()
.border_t_1()
.border_color(cx.theme().colors().border_variant)
.border_color(cx.theme().colors().border)
.child(self.message_editor.clone()),
)
.children(self.render_last_error(cx)),

View file

@ -9,7 +9,7 @@ use gpui::{
WeakModel, WeakView,
};
use picker::{Picker, PickerDelegate};
use ui::{prelude::*, ListItem, ListItemSpacing, Tooltip};
use ui::{prelude::*, ListItem, ListItemSpacing};
use util::ResultExt;
use workspace::Workspace;
@ -41,27 +41,23 @@ impl ContextPicker {
) -> Self {
let mut entries = vec![
ContextPickerEntry {
name: "directory".into(),
description: "Insert any directory".into(),
name: "Directory".into(),
icon: IconName::Folder,
},
ContextPickerEntry {
name: "file".into(),
description: "Insert any file".into(),
name: "File".into(),
icon: IconName::File,
},
ContextPickerEntry {
name: "fetch".into(),
description: "Fetch content from URL".into(),
name: "Fetch".into(),
icon: IconName::Globe,
},
];
if thread_store.is_some() {
entries.push(ContextPickerEntry {
name: "thread".into(),
description: "Insert any thread".into(),
icon: IconName::MessageBubbles,
name: "Thread".into(),
icon: IconName::MessageCircle,
});
}
@ -119,7 +115,6 @@ impl Render for ContextPicker {
#[derive(Clone)]
struct ContextPickerEntry {
name: SharedString,
description: SharedString,
icon: IconName,
}
@ -161,7 +156,7 @@ impl PickerDelegate for ContextPickerDelegate {
self.context_picker
.update(cx, |this, cx| {
match entry.name.to_string().as_str() {
"file" => {
"File" => {
this.mode = ContextPickerMode::File(cx.new_view(|cx| {
FileContextPicker::new(
self.context_picker.clone(),
@ -171,7 +166,7 @@ impl PickerDelegate for ContextPickerDelegate {
)
}));
}
"fetch" => {
"Fetch" => {
this.mode = ContextPickerMode::Fetch(cx.new_view(|cx| {
FetchContextPicker::new(
self.context_picker.clone(),
@ -181,7 +176,7 @@ impl PickerDelegate for ContextPickerDelegate {
)
}));
}
"thread" => {
"Thread" => {
if let Some(thread_store) = self.thread_store.as_ref() {
this.mode = ContextPickerMode::Thread(cx.new_view(|cx| {
ThreadContextPicker::new(
@ -226,34 +221,13 @@ impl PickerDelegate for ContextPickerDelegate {
.inset(true)
.spacing(ListItemSpacing::Dense)
.toggle_state(selected)
.tooltip({
let description = entry.description.clone();
move |cx| cx.new_view(|_cx| Tooltip::new(description.clone())).into()
})
.child(
v_flex()
.group(format!("context-entry-label-{ix}"))
.w_full()
.py_0p5()
h_flex()
.min_w(px(250.))
.max_w(px(400.))
.child(
h_flex()
.gap_1p5()
.child(Icon::new(entry.icon).size(IconSize::XSmall))
.child(
Label::new(entry.name.clone())
.single_line()
.size(LabelSize::Small),
),
)
.child(
div().overflow_hidden().text_ellipsis().child(
Label::new(entry.description.clone())
.size(LabelSize::Small)
.color(Color::Muted),
),
),
.gap_2()
.child(Icon::new(entry.icon).size(IconSize::Small))
.child(Label::new(entry.name.clone()).single_line()),
),
)
}

View file

@ -1,7 +1,7 @@
use std::rc::Rc;
use gpui::{Model, View, WeakModel, WeakView};
use ui::{prelude::*, IconButtonShape, PopoverMenu, PopoverMenuHandle, Tooltip};
use ui::{prelude::*, PopoverMenu, PopoverMenuHandle, Tooltip};
use workspace::Workspace;
use crate::context_picker::ContextPicker;
@ -44,14 +44,14 @@ impl Render for ContextStrip {
h_flex()
.flex_wrap()
.gap_2()
.gap_1()
.child(
PopoverMenu::new("context-picker")
.menu(move |_cx| Some(context_picker.clone()))
.trigger(
IconButton::new("add-context", IconName::Plus)
.shape(IconButtonShape::Square)
.icon_size(IconSize::Small),
.icon_size(IconSize::Small)
.style(ui::ButtonStyle::Filled),
)
.attach(gpui::AnchorCorner::TopLeft)
.anchor(gpui::AnchorCorner::BottomLeft)
@ -76,7 +76,6 @@ impl Render for ContextStrip {
.when(!context.is_empty(), |parent| {
parent.child(
IconButton::new("remove-all-context", IconName::Eraser)
.shape(IconButtonShape::Square)
.icon_size(IconSize::Small)
.tooltip(move |cx| Tooltip::text("Remove All Context", cx))
.on_click({

View file

@ -35,7 +35,8 @@ impl MessageEditor {
thread,
editor: cx.new_view(|cx| {
let mut editor = Editor::auto_height(80, cx);
editor.set_placeholder_text("Ask anything or type @ to add context", cx);
editor.set_placeholder_text("Ask anything, @ to add context", cx);
editor.set_show_indent_guides(false, cx);
editor
}),
@ -112,8 +113,8 @@ impl MessageEditor {
}
fn render_language_model_selector(&self, cx: &mut ViewContext<Self>) -> impl IntoElement {
let active_provider = LanguageModelRegistry::read_global(cx).active_provider();
let active_model = LanguageModelRegistry::read_global(cx).active_model();
let focus_handle = self.language_model_selector.focus_handle(cx).clone();
LanguageModelSelectorPopoverMenu::new(
self.language_model_selector.clone(),
@ -128,16 +129,8 @@ impl MessageEditor {
.overflow_x_hidden()
.flex_grow()
.whitespace_nowrap()
.child(match (active_provider, active_model) {
(Some(provider), Some(model)) => h_flex()
.gap_1()
.child(
Icon::new(
model.icon().unwrap_or_else(|| provider.icon()),
)
.color(Color::Muted)
.size(IconSize::XSmall),
)
.child(match active_model {
Some(model) => h_flex()
.child(
Label::new(model.name().0)
.size(LabelSize::Small)
@ -156,7 +149,9 @@ impl MessageEditor {
.size(IconSize::XSmall),
),
)
.tooltip(move |cx| Tooltip::for_action("Change Model", &ToggleModelSelector, cx)),
.tooltip(move |cx| {
Tooltip::for_action_in("Change Model", &ToggleModelSelector, &focus_handle, cx)
}),
)
}
}
@ -170,8 +165,9 @@ impl FocusableView for MessageEditor {
impl Render for MessageEditor {
fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
let font_size = TextSize::Default.rems(cx);
let line_height = font_size.to_pixels(cx.rem_size()) * 1.3;
let line_height = font_size.to_pixels(cx.rem_size()) * 1.5;
let focus_handle = self.editor.focus_handle(cx);
let bg_color = cx.theme().colors().editor_background;
v_flex()
.key_context("MessageEditor")
@ -179,9 +175,9 @@ impl Render for MessageEditor {
.size_full()
.gap_2()
.p_2()
.bg(cx.theme().colors().editor_background)
.bg(bg_color)
.child(self.context_strip.clone())
.child({
.child(div().id("thread_editor").overflow_y_scroll().h_12().child({
let settings = ThemeSettings::get_global(cx);
let text_style = TextStyle {
color: cx.theme().colors().editor_foreground,
@ -196,17 +192,17 @@ impl Render for MessageEditor {
EditorElement::new(
&self.editor,
EditorStyle {
background: cx.theme().colors().editor_background,
background: bg_color,
local_player: cx.theme().players().local(),
text: text_style,
..Default::default()
},
)
})
}))
.child(
h_flex()
.justify_between()
.child(h_flex().gap_2().child(CheckboxWithLabel::new(
.child(CheckboxWithLabel::new(
"use-tools",
Label::new("Tools"),
self.use_tools.into(),
@ -216,10 +212,10 @@ impl Render for MessageEditor {
ToggleState::Unselected | ToggleState::Indeterminate => false,
};
}),
)))
))
.child(
h_flex()
.gap_2()
.gap_1()
.child(self.render_language_model_selector(cx))
.child(
ButtonLike::new("chat")

View file

@ -120,7 +120,11 @@ impl RenderOnce for PastThread {
ListItem::new(("past-thread", self.thread.entity_id()))
.outlined()
.start_slot(Icon::new(IconName::MessageBubbles))
.start_slot(
Icon::new(IconName::MessageCircle)
.size(IconSize::Small)
.color(Color::Muted),
)
.spacing(ListItemSpacing::Sparse)
.child(Label::new(summary).size(LabelSize::Small))
.end_slot(

View file

@ -29,9 +29,12 @@ impl RenderOnce for ContextPill {
fn render(self, cx: &mut WindowContext) -> impl IntoElement {
h_flex()
.gap_1()
.px_1()
.pl_1p5()
.pr_0p5()
.pb(px(1.))
.border_1()
.border_color(cx.theme().colors().border)
.border_color(cx.theme().colors().border.opacity(0.5))
.bg(cx.theme().colors().element_background)
.rounded_md()
.child(Label::new(self.context.name.clone()).size(LabelSize::Small))
.when_some(self.on_remove, |parent, on_remove| {

View file

@ -218,6 +218,7 @@ pub enum IconName {
Maximize,
Menu,
MessageBubbles,
MessageCircle,
Mic,
MicMute,
Microscope,