assistant2: Adjust elements in the message editor (#27696)

Danilo Leal created

Most notable change in this PR is the changing the default profiles'
names to just "Write" and "Ask". Everything else is mostly
design-related. Here's how it looks like:

<img
src="https://github.com/user-attachments/assets/791948c9-2d63-4523-9d54-08b63a00be6a"
width="600" />

Release Notes:

- N/A

Change summary

assets/icons/user_round_pen.svg           |  1 
assets/settings/default.json              | 10 +-
crates/assistant2/src/profile_selector.rs | 74 +++++++++++++++---------
crates/assistant2/src/ui/context_pill.rs  |  6 +
crates/icons/src/icons.rs                 |  1 
5 files changed, 59 insertions(+), 33 deletions(-)

Detailed changes

assets/icons/user_round_pen.svg 🔗

@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-user-round-pen-icon lucide-user-round-pen"><path d="M2 21a8 8 0 0 1 10.821-7.487"/><path d="M21.378 16.626a1 1 0 0 0-3.004-3.004l-4.01 4.012a2 2 0 0 0-.506.854l-.837 2.87a.5.5 0 0 0 .62.62l2.87-.837a2 2 0 0 0 .854-.506z"/><circle cx="10" cy="8" r="5"/></svg>

assets/settings/default.json 🔗

@@ -633,10 +633,10 @@
       // The model to use.
       "model": "claude-3-5-sonnet-latest"
     },
-    "default_profile": "code-writer",
+    "default_profile": "write",
     "profiles": {
-      "read-only": {
-        "name": "Read-only",
+      "ask": {
+        "name": "Ask",
         "tools": {
           "diagnostics": true,
           "fetch": true,
@@ -648,8 +648,8 @@
           "thinking": true
         }
       },
-      "code-writer": {
-        "name": "Code Writer",
+      "write": {
+        "name": "Write",
         "tools": {
           "bash": true,
           "batch-tool": true,

crates/assistant2/src/profile_selector.rs 🔗

@@ -5,7 +5,10 @@ use fs::Fs;
 use gpui::{prelude::*, Action, Entity, FocusHandle, Subscription, WeakEntity};
 use indexmap::IndexMap;
 use settings::{update_settings_file, Settings as _, SettingsStore};
-use ui::{prelude::*, ContextMenu, ContextMenuEntry, PopoverMenu, PopoverMenuHandle, Tooltip};
+use ui::{
+    prelude::*, ButtonLike, ContextMenu, ContextMenuEntry, KeyBinding, PopoverMenu,
+    PopoverMenuHandle,
+};
 use util::ResultExt as _;
 
 use crate::{ManageProfiles, ThreadStore, ToggleProfileSelector};
@@ -60,7 +63,7 @@ impl ProfileSelector {
     ) -> Entity<ContextMenu> {
         ContextMenu::build(window, cx, |mut menu, _window, cx| {
             let settings = AssistantSettings::get_global(cx);
-            let icon_position = IconPosition::Start;
+            let icon_position = IconPosition::End;
 
             menu = menu.header("Profiles");
             for (profile_id, profile) in self.profiles.clone() {
@@ -91,14 +94,11 @@ impl ProfileSelector {
             }
 
             menu = menu.separator();
-            menu = menu.item(
-                ContextMenuEntry::new("Configure Profiles")
-                    .icon(IconName::Pencil)
-                    .icon_color(Color::Muted)
-                    .handler(move |window, cx| {
-                        window.dispatch_action(ManageProfiles.boxed_clone(), cx);
-                    }),
-            );
+            menu = menu.item(ContextMenuEntry::new("Configure Profiles").handler(
+                move |window, cx| {
+                    window.dispatch_action(ManageProfiles.boxed_clone(), cx);
+                },
+            ));
 
             menu
         })
@@ -106,33 +106,53 @@ impl ProfileSelector {
 }
 
 impl Render for ProfileSelector {
-    fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
+    fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
         let settings = AssistantSettings::get_global(cx);
-        let profile = settings
-            .profiles
-            .get(&settings.default_profile)
+        let profile_id = &settings.default_profile;
+        let profile = settings.profiles.get(profile_id);
+
+        let selected_profile = profile
             .map(|profile| profile.name.clone())
             .unwrap_or_else(|| "Unknown".into());
 
+        let icon = match profile_id.as_ref() {
+            "write" => IconName::Pencil,
+            "ask" => IconName::MessageBubbles,
+            _ => IconName::UserRoundPen,
+        };
+
         let this = cx.entity().clone();
         let focus_handle = self.focus_handle.clone();
         PopoverMenu::new("profile-selector")
             .menu(move |window, cx| {
                 Some(this.update(cx, |this, cx| this.build_context_menu(window, cx)))
             })
-            .trigger_with_tooltip(
-                Button::new("profile-selector-button", profile)
-                    .style(ButtonStyle::Filled)
-                    .label_size(LabelSize::Small),
-                move |window, cx| {
-                    Tooltip::for_action_in(
-                        "Change Profile",
-                        &ToggleProfileSelector,
-                        &focus_handle,
-                        window,
-                        cx,
-                    )
-                },
+            .trigger(
+                ButtonLike::new("profile-selector-button").child(
+                    h_flex()
+                        .gap_1()
+                        .child(Icon::new(icon).size(IconSize::XSmall).color(Color::Muted))
+                        .child(
+                            Label::new(selected_profile)
+                                .size(LabelSize::Small)
+                                .color(Color::Muted),
+                        )
+                        .child(
+                            Icon::new(IconName::ChevronDown)
+                                .size(IconSize::XSmall)
+                                .color(Color::Muted),
+                        )
+                        .child(div().opacity(0.5).children({
+                            let focus_handle = focus_handle.clone();
+                            KeyBinding::for_action_in(
+                                &ToggleProfileSelector,
+                                &focus_handle,
+                                window,
+                                cx,
+                            )
+                            .map(|kb| kb.size(rems_from_px(10.)))
+                        })),
+                ),
             )
             .anchor(gpui::Corner::BottomLeft)
             .with_handle(self.menu_handle.clone())

crates/assistant2/src/ui/context_pill.rs 🔗

@@ -175,10 +175,14 @@ impl RenderOnce for ContextPill {
             } => base_pill
                 .cursor_pointer()
                 .pr_1()
+                .when(*focused, |this| {
+                    this.bg(color.element_background.opacity(0.5))
+                })
+                .border_dashed()
                 .border_color(if *focused {
                     color.border_focused
                 } else {
-                    color.border_variant.opacity(0.5)
+                    color.border
                 })
                 .hover(|style| style.bg(color.element_hover.opacity(0.5)))
                 .child(