Skip to content

Commit 5c400da

Browse files
authored
assistant2: Adjust empty state layout (#25745)
Going for a different, arguably simpler design for the Assistant 2 empty state here. Also took the opportunity to adjust other elements like the toolbar, message editor, and some items in the configuration page. <img src="https://github.com/user-attachments/assets/03fd1d48-a675-4eac-b694-bbe4eeaf06e9" width="700px"/> Release Notes: - N/A
1 parent 635b80e commit 5c400da

File tree

7 files changed

+186
-136
lines changed

7 files changed

+186
-136
lines changed

crates/assistant2/src/assistant_configuration.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -158,8 +158,16 @@ impl Render for AssistantConfiguration {
158158
.child(
159159
v_flex()
160160
.p(DynamicSpacing::Base16.rems(cx))
161-
.gap_1()
162-
.child(Headline::new("Prompt Library").size(HeadlineSize::Small))
161+
.gap_2()
162+
.child(
163+
v_flex()
164+
.gap_0p5()
165+
.child(Headline::new("Prompt Library").size(HeadlineSize::Small))
166+
.child(
167+
Label::new("Create reusable prompts and tag which ones you want sent in every LLM interaction.")
168+
.color(Color::Muted),
169+
),
170+
)
163171
.child(
164172
Button::new("open-prompt-library", "Open Prompt Library")
165173
.style(ButtonStyle::Filled)

crates/assistant2/src/assistant_panel.rs

Lines changed: 110 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use client::zed_urls;
1414
use editor::Editor;
1515
use fs::Fs;
1616
use gpui::{
17-
prelude::*, px, svg, Action, AnyElement, App, AsyncWindowContext, Corner, Entity, EventEmitter,
17+
prelude::*, Action, AnyElement, App, AsyncWindowContext, Corner, Entity, EventEmitter,
1818
FocusHandle, Focusable, FontWeight, Pixels, Subscription, Task, UpdateGlobal, WeakEntity,
1919
};
2020
use language::LanguageRegistry;
@@ -596,80 +596,93 @@ impl AssistantPanel {
596596

597597
h_flex()
598598
.id("assistant-toolbar")
599-
.px(DynamicSpacing::Base08.rems(cx))
600599
.h(Tab::container_height(cx))
601600
.flex_none()
602601
.justify_between()
603602
.gap(DynamicSpacing::Base08.rems(cx))
604603
.bg(cx.theme().colors().tab_bar_background)
605604
.border_b_1()
606605
.border_color(cx.theme().colors().border)
606+
.child(
607+
div()
608+
.id("title")
609+
.overflow_x_scroll()
610+
.px(DynamicSpacing::Base08.rems(cx))
611+
.child(Label::new(title).text_ellipsis()),
612+
)
607613
.child(
608614
h_flex()
609-
.w_full()
610-
.gap_1()
611-
.justify_between()
612-
.child(Label::new(title))
615+
.h_full()
616+
.pl_2()
617+
.gap_2()
618+
.bg(cx.theme().colors().tab_bar_background)
613619
.children(if matches!(self.active_view, ActiveView::PromptEditor) {
614620
self.context_editor
615621
.as_ref()
616622
.and_then(|editor| render_remaining_tokens(editor, cx))
617623
} else {
618624
None
619-
}),
620-
)
621-
.child(
622-
h_flex()
623-
.h_full()
624-
.pl_1p5()
625-
.border_l_1()
626-
.border_color(cx.theme().colors().border)
627-
.gap(DynamicSpacing::Base02.rems(cx))
625+
})
628626
.child(
629-
PopoverMenu::new("assistant-toolbar-new-popover-menu")
630-
.trigger_with_tooltip(
631-
IconButton::new("new", IconName::Plus)
627+
h_flex()
628+
.h_full()
629+
.px(DynamicSpacing::Base08.rems(cx))
630+
.border_l_1()
631+
.border_color(cx.theme().colors().border)
632+
.gap(DynamicSpacing::Base02.rems(cx))
633+
.child(
634+
PopoverMenu::new("assistant-toolbar-new-popover-menu")
635+
.trigger_with_tooltip(
636+
IconButton::new("new", IconName::Plus)
637+
.icon_size(IconSize::Small)
638+
.style(ButtonStyle::Subtle),
639+
Tooltip::text("New…"),
640+
)
641+
.anchor(Corner::TopRight)
642+
.with_handle(self.new_item_context_menu_handle.clone())
643+
.menu(move |window, cx| {
644+
Some(ContextMenu::build(
645+
window,
646+
cx,
647+
|menu, _window, _cx| {
648+
menu.action("New Thread", NewThread.boxed_clone())
649+
.action(
650+
"New Prompt Editor",
651+
NewPromptEditor.boxed_clone(),
652+
)
653+
},
654+
))
655+
}),
656+
)
657+
.child(
658+
IconButton::new("open-history", IconName::HistoryRerun)
632659
.icon_size(IconSize::Small)
633-
.style(ButtonStyle::Subtle),
634-
Tooltip::text("New…"),
660+
.style(ButtonStyle::Subtle)
661+
.tooltip({
662+
let focus_handle = self.focus_handle(cx);
663+
move |window, cx| {
664+
Tooltip::for_action_in(
665+
"History",
666+
&OpenHistory,
667+
&focus_handle,
668+
window,
669+
cx,
670+
)
671+
}
672+
})
673+
.on_click(move |_event, window, cx| {
674+
window.dispatch_action(OpenHistory.boxed_clone(), cx);
675+
}),
635676
)
636-
.anchor(Corner::TopRight)
637-
.with_handle(self.new_item_context_menu_handle.clone())
638-
.menu(move |window, cx| {
639-
Some(ContextMenu::build(window, cx, |menu, _window, _cx| {
640-
menu.action("New Thread", NewThread.boxed_clone())
641-
.action("New Prompt Editor", NewPromptEditor.boxed_clone())
642-
}))
643-
}),
644-
)
645-
.child(
646-
IconButton::new("open-history", IconName::HistoryRerun)
647-
.icon_size(IconSize::Small)
648-
.style(ButtonStyle::Subtle)
649-
.tooltip({
650-
let focus_handle = self.focus_handle(cx);
651-
move |window, cx| {
652-
Tooltip::for_action_in(
653-
"History",
654-
&OpenHistory,
655-
&focus_handle,
656-
window,
657-
cx,
658-
)
659-
}
660-
})
661-
.on_click(move |_event, window, cx| {
662-
window.dispatch_action(OpenHistory.boxed_clone(), cx);
663-
}),
664-
)
665-
.child(
666-
IconButton::new("configure-assistant", IconName::Settings)
667-
.icon_size(IconSize::Small)
668-
.style(ButtonStyle::Subtle)
669-
.tooltip(Tooltip::text("Assistant Settings"))
670-
.on_click(move |_event, window, cx| {
671-
window.dispatch_action(OpenConfiguration.boxed_clone(), cx);
672-
}),
677+
.child(
678+
IconButton::new("configure-assistant", IconName::Settings)
679+
.icon_size(IconSize::Small)
680+
.style(ButtonStyle::Subtle)
681+
.tooltip(Tooltip::text("Assistant Settings"))
682+
.on_click(move |_event, window, cx| {
683+
window.dispatch_action(OpenConfiguration.boxed_clone(), cx);
684+
}),
685+
),
673686
),
674687
)
675688
}
@@ -711,49 +724,39 @@ impl AssistantPanel {
711724
) -> impl IntoElement {
712725
let recent_history = self
713726
.history_store
714-
.update(cx, |this, cx| this.recent_entries(3, cx));
727+
.update(cx, |this, cx| this.recent_entries(6, cx));
715728

716729
let create_welcome_heading = || {
717730
h_flex()
718731
.w_full()
719-
.justify_center()
720732
.child(Headline::new("Welcome to the Assistant Panel").size(HeadlineSize::Small))
721733
};
722734

723735
let configuration_error = self.configuration_error(cx);
724736
let no_error = configuration_error.is_none();
725737

726738
v_flex()
727-
.gap_2()
728-
.child(
729-
v_flex().w_full().child(
730-
svg()
731-
.path("icons/logo_96.svg")
732-
.text_color(cx.theme().colors().text)
733-
.w(px(40.))
734-
.h(px(40.))
735-
.mx_auto()
736-
.mb_4(),
737-
),
738-
)
739+
.p_1p5()
740+
.size_full()
741+
.justify_end()
742+
.gap_1()
739743
.map(|parent| {
740744
match configuration_error {
741745
Some(ConfigurationError::ProviderNotAuthenticated)
742746
| Some(ConfigurationError::NoProvider) => {
743747
parent.child(
744748
v_flex()
749+
.px_1p5()
745750
.gap_0p5()
746751
.child(create_welcome_heading())
747752
.child(
748-
h_flex().mb_2().w_full().justify_center().child(
749-
Label::new(
750-
"To start using the assistant, configure at least one LLM provider.",
751-
)
752-
.color(Color::Muted),
753-
),
753+
Label::new(
754+
"To start using the assistant, configure at least one LLM provider.",
755+
)
756+
.color(Color::Muted),
754757
)
755758
.child(
756-
h_flex().w_full().justify_center().child(
759+
h_flex().mt_1().w_full().child(
757760
Button::new("open-configuration", "Configure a Provider")
758761
.size(ButtonSize::Compact)
759762
.icon(Some(IconName::Sliders))
@@ -767,7 +770,7 @@ impl AssistantPanel {
767770
)
768771
}
769772
Some(ConfigurationError::ProviderPendingTermsAcceptance(provider)) => parent
770-
.child(v_flex().gap_0p5().child(create_welcome_heading()).children(
773+
.child(v_flex().px_1p5().gap_0p5().child(create_welcome_heading()).children(
771774
provider.render_accept_terms(
772775
LanguageModelProviderTosView::ThreadEmptyState,
773776
cx,
@@ -778,21 +781,40 @@ impl AssistantPanel {
778781
})
779782
.when(recent_history.is_empty() && no_error, |parent| {
780783
parent.child(v_flex().gap_0p5().child(create_welcome_heading()).child(
781-
h_flex().w_full().justify_center().child(
782-
Label::new("Start typing to chat with your codebase").color(Color::Muted),
783-
),
784+
Label::new("Start typing to chat with your codebase").color(Color::Muted),
784785
))
785786
})
786787
.when(!recent_history.is_empty(), |parent| {
787788
parent
788789
.child(
789-
h_flex().w_full().justify_center().child(
790-
Label::new("Recent Threads:")
791-
.size(LabelSize::Small)
792-
.color(Color::Muted),
793-
),
790+
h_flex()
791+
.pl_1p5()
792+
.pb_1()
793+
.w_full()
794+
.justify_between()
795+
.border_b_1()
796+
.border_color(cx.theme().colors().border_variant)
797+
.child(
798+
Label::new("Past Interactions")
799+
.size(LabelSize::Small)
800+
.color(Color::Muted),
801+
)
802+
.child(
803+
Button::new("view-history", "View All")
804+
.style(ButtonStyle::Subtle)
805+
.label_size(LabelSize::Small)
806+
.key_binding(KeyBinding::for_action_in(
807+
&OpenHistory,
808+
&self.focus_handle(cx),
809+
window,
810+
cx,
811+
))
812+
.on_click(move |_event, window, cx| {
813+
window.dispatch_action(OpenHistory.boxed_clone(), cx);
814+
}),
815+
),
794816
)
795-
.child(v_flex().mx_auto().w_4_5().gap_2().children(
817+
.child(v_flex().gap_1().children(
796818
recent_history.into_iter().map(|entry| {
797819
// TODO: Add keyboard navigation.
798820
match entry {
@@ -807,22 +829,6 @@ impl AssistantPanel {
807829
}
808830
}),
809831
))
810-
.child(
811-
h_flex().w_full().justify_center().child(
812-
Button::new("view-all-past-threads", "View All Past Threads")
813-
.style(ButtonStyle::Subtle)
814-
.label_size(LabelSize::Small)
815-
.key_binding(KeyBinding::for_action_in(
816-
&OpenHistory,
817-
&self.focus_handle(cx),
818-
window,
819-
cx,
820-
))
821-
.on_click(move |_event, window, cx| {
822-
window.dispatch_action(OpenHistory.boxed_clone(), cx);
823-
}),
824-
),
825-
)
826832
})
827833
}
828834

crates/assistant2/src/message_editor.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -314,7 +314,7 @@ impl Render for MessageEditor {
314314
.child(self.context_strip.clone())
315315
.child(
316316
v_flex()
317-
.gap_4()
317+
.gap_5()
318318
.child({
319319
let settings = ThemeSettings::get_global(cx);
320320
let text_style = TextStyle {

crates/assistant2/src/thread_history.rs

Lines changed: 32 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -254,18 +254,28 @@ impl RenderOnce for PastThread {
254254
);
255255

256256
ListItem::new(SharedString::from(self.thread.id.to_string()))
257-
.outlined()
257+
.rounded()
258258
.toggle_state(self.selected)
259+
.spacing(ListItemSpacing::Sparse)
259260
.start_slot(
260-
Icon::new(IconName::MessageCircle)
261-
.size(IconSize::Small)
262-
.color(Color::Muted),
261+
div()
262+
.max_w_4_5()
263+
.child(Label::new(summary).size(LabelSize::Small).text_ellipsis()),
263264
)
264-
.spacing(ListItemSpacing::Sparse)
265-
.child(Label::new(summary).size(LabelSize::Small).text_ellipsis())
266265
.end_slot(
267266
h_flex()
268267
.gap_1p5()
268+
.child(
269+
Label::new("Thread")
270+
.color(Color::Muted)
271+
.size(LabelSize::XSmall),
272+
)
273+
.child(
274+
div()
275+
.size(px(3.))
276+
.rounded_full()
277+
.bg(cx.theme().colors().text_disabled),
278+
)
269279
.child(
270280
Label::new(thread_timestamp)
271281
.color(Color::Muted)
@@ -340,18 +350,28 @@ impl RenderOnce for PastContext {
340350
ListItem::new(SharedString::from(
341351
self.context.path.to_string_lossy().to_string(),
342352
))
343-
.outlined()
353+
.rounded()
344354
.toggle_state(self.selected)
355+
.spacing(ListItemSpacing::Sparse)
345356
.start_slot(
346-
Icon::new(IconName::Code)
347-
.size(IconSize::Small)
348-
.color(Color::Muted),
357+
div()
358+
.max_w_4_5()
359+
.child(Label::new(summary).size(LabelSize::Small).text_ellipsis()),
349360
)
350-
.spacing(ListItemSpacing::Sparse)
351-
.child(Label::new(summary).size(LabelSize::Small).text_ellipsis())
352361
.end_slot(
353362
h_flex()
354363
.gap_1p5()
364+
.child(
365+
Label::new("Prompt Editor")
366+
.color(Color::Muted)
367+
.size(LabelSize::XSmall),
368+
)
369+
.child(
370+
div()
371+
.size(px(3.))
372+
.rounded_full()
373+
.bg(cx.theme().colors().text_disabled),
374+
)
355375
.child(
356376
Label::new(context_timestamp)
357377
.color(Color::Muted)

0 commit comments

Comments
 (0)