agent: Improve pickers and their triggers styles in the panel (#40284)

Making all triggers have the same style when the picker is open
(including changing the icon when the picker opens on top of the
trigger). Also removed the footer from the ACP model selector given
there's nothing to consider when that's the case; users can only
configure LLM providers when using Zed's built-in agent.

Release Notes:

- N/A
This commit is contained in:
Danilo Leal
2025-10-15 19:50:44 -03:00
committed by GitHub
parent 28e14a361d
commit f4609c04eb
7 changed files with 65 additions and 72 deletions
+7 -2
View File
@@ -174,11 +174,16 @@ impl Render for ModeSelector {
let this = cx.entity();
let icon = if self.menu_handle.is_deployed() {
IconName::ChevronUp
} else {
IconName::ChevronDown
};
let trigger_button = Button::new("mode-selector-trigger", current_mode_name)
.label_size(LabelSize::Small)
.style(ButtonStyle::Subtle)
.color(Color::Muted)
.icon(IconName::ChevronDown)
.icon(icon)
.icon_size(IconSize::XSmall)
.icon_position(IconPosition::End)
.icon_color(Color::Muted)
+4 -34
View File
@@ -5,12 +5,12 @@ use anyhow::Result;
use collections::IndexMap;
use futures::FutureExt;
use fuzzy::{StringMatchCandidate, match_strings};
use gpui::{Action, AsyncWindowContext, BackgroundExecutor, DismissEvent, Task, WeakEntity};
use gpui::{AsyncWindowContext, BackgroundExecutor, DismissEvent, Task, WeakEntity};
use ordered_float::OrderedFloat;
use picker::{Picker, PickerDelegate};
use ui::{
AnyElement, App, Context, DocumentationAside, DocumentationEdge, DocumentationSide,
IntoElement, ListItem, ListItemSpacing, SharedString, Window, prelude::*, rems,
DocumentationAside, DocumentationEdge, DocumentationSide, IntoElement, ListItem,
ListItemSpacing, prelude::*,
};
use util::ResultExt;
@@ -278,36 +278,6 @@ impl PickerDelegate for AcpModelPickerDelegate {
}
}
fn render_footer(
&self,
_: &mut Window,
cx: &mut Context<Picker<Self>>,
) -> Option<gpui::AnyElement> {
Some(
h_flex()
.w_full()
.border_t_1()
.border_color(cx.theme().colors().border_variant)
.p_1()
.gap_4()
.justify_between()
.child(
Button::new("configure", "Configure")
.icon(IconName::Settings)
.icon_size(IconSize::Small)
.icon_color(Color::Muted)
.icon_position(IconPosition::Start)
.on_click(|_, window, cx| {
window.dispatch_action(
zed_actions::agent::OpenSettings.boxed_clone(),
cx,
);
}),
)
.into_any(),
)
}
fn documentation_aside(
&self,
_window: &mut Window,
@@ -317,7 +287,7 @@ impl PickerDelegate for AcpModelPickerDelegate {
let description = description.clone();
DocumentationAside::new(
DocumentationSide::Left,
DocumentationEdge::Bottom,
DocumentationEdge::Top,
Rc::new(move |_| Label::new(description.clone()).into_any_element()),
)
})
@@ -57,30 +57,26 @@ impl Render for AcpModelSelectorPopover {
let focus_handle = self.focus_handle.clone();
let color = if self.menu_handle.is_deployed() {
Color::Accent
let (color, icon) = if self.menu_handle.is_deployed() {
(Color::Accent, IconName::ChevronUp)
} else {
Color::Muted
(Color::Muted, IconName::ChevronDown)
};
PickerPopoverMenu::new(
self.selector.clone(),
ButtonLike::new("active-model")
.selected_style(ButtonStyle::Tinted(TintColor::Accent))
.when_some(model_icon, |this, icon| {
this.child(Icon::new(icon).color(color).size(IconSize::XSmall))
})
.selected_style(ButtonStyle::Tinted(TintColor::Accent))
.child(
Label::new(model_name)
.color(color)
.size(LabelSize::Small)
.ml_0p5(),
)
.child(
Icon::new(IconName::ChevronDown)
.color(Color::Muted)
.size(IconSize::XSmall),
),
.child(Icon::new(icon).color(Color::Muted).size(IconSize::XSmall)),
move |window, cx| {
Tooltip::for_action_in(
"Change Model",
+15 -5
View File
@@ -7,7 +7,7 @@ use gpui::{Entity, FocusHandle, SharedString};
use picker::popover_menu::PickerPopoverMenu;
use settings::update_settings_file;
use std::sync::Arc;
use ui::{ButtonLike, PopoverMenuHandle, Tooltip, prelude::*};
use ui::{ButtonLike, PopoverMenuHandle, TintColor, Tooltip, prelude::*};
use zed_actions::agent::ToggleModelSelector;
pub struct AgentModelSelector {
@@ -70,6 +70,11 @@ impl Render for AgentModelSelector {
.unwrap_or_else(|| SharedString::from("Select a Model"));
let provider_icon = model.as_ref().map(|model| model.provider.icon());
let color = if self.menu_handle.is_deployed() {
Color::Accent
} else {
Color::Muted
};
let focus_handle = self.focus_handle.clone();
@@ -77,17 +82,18 @@ impl Render for AgentModelSelector {
self.selector.clone(),
ButtonLike::new("active-model")
.when_some(provider_icon, |this, icon| {
this.child(Icon::new(icon).color(Color::Muted).size(IconSize::XSmall))
this.child(Icon::new(icon).color(color).size(IconSize::XSmall))
})
.selected_style(ButtonStyle::Tinted(TintColor::Accent))
.child(
Label::new(model_name)
.color(Color::Muted)
.color(color)
.size(LabelSize::Small)
.ml_0p5(),
)
.child(
Icon::new(IconName::ChevronDown)
.color(Color::Muted)
.color(color)
.size(IconSize::XSmall),
),
move |window, cx| {
@@ -99,10 +105,14 @@ impl Render for AgentModelSelector {
cx,
)
},
gpui::Corner::BottomRight,
gpui::Corner::TopRight,
cx,
)
.with_handle(self.menu_handle.clone())
.offset(gpui::Point {
x: px(0.0),
y: px(2.0),
})
.render(window, cx)
}
}
+7 -1
View File
@@ -144,10 +144,16 @@ impl Render for ProfileSelector {
.unwrap_or_else(|| "Unknown".into());
let focus_handle = self.focus_handle.clone();
let icon = if self.picker_handle.is_deployed() {
IconName::ChevronUp
} else {
IconName::ChevronDown
};
let trigger_button = Button::new("profile-selector", selected_profile)
.label_size(LabelSize::Small)
.color(Color::Muted)
.icon(IconName::ChevronDown)
.icon(icon)
.icon_size(IconSize::XSmall)
.icon_position(IconPosition::End)
.icon_color(Color::Muted)
+13 -14
View File
@@ -1977,7 +1977,9 @@ impl TextThreadEditor {
cx.entity().downgrade(),
IconButton::new("trigger", IconName::Plus)
.icon_size(IconSize::Small)
.icon_color(Color::Muted),
.icon_color(Color::Muted)
.selected_icon_color(Color::Accent)
.selected_style(ButtonStyle::Filled),
move |window, cx| {
Tooltip::with_meta(
"Add Context",
@@ -2052,30 +2054,27 @@ impl TextThreadEditor {
};
let focus_handle = self.editor().focus_handle(cx);
let (color, icon) = if self.language_model_selector_menu_handle.is_deployed() {
(Color::Accent, IconName::ChevronUp)
} else {
(Color::Muted, IconName::ChevronDown)
};
PickerPopoverMenu::new(
self.language_model_selector.clone(),
ButtonLike::new("active-model")
.style(ButtonStyle::Subtle)
.selected_style(ButtonStyle::Tinted(TintColor::Accent))
.child(
h_flex()
.gap_0p5()
.child(
Icon::new(provider_icon)
.color(Color::Muted)
.size(IconSize::XSmall),
)
.child(Icon::new(provider_icon).color(color).size(IconSize::XSmall))
.child(
Label::new(model_name)
.color(Color::Muted)
.color(color)
.size(LabelSize::Small)
.ml_0p5(),
)
.child(
Icon::new(IconName::ChevronDown)
.color(Color::Muted)
.size(IconSize::XSmall),
),
.child(Icon::new(icon).color(color).size(IconSize::XSmall)),
),
move |window, cx| {
Tooltip::for_action_in(
@@ -2086,7 +2085,7 @@ impl TextThreadEditor {
cx,
)
},
gpui::Corner::BottomLeft,
gpui::Corner::BottomRight,
cx,
)
.with_handle(self.language_model_selector_menu_handle.clone())
+14 -7
View File
@@ -1,9 +1,9 @@
use gpui::{
AnyView, Corner, DismissEvent, Entity, EventEmitter, FocusHandle, Focusable, Subscription,
AnyView, Corner, DismissEvent, Entity, EventEmitter, FocusHandle, Focusable, Pixels, Point,
Subscription,
};
use ui::{
App, ButtonCommon, FluentBuilder as _, IntoElement, PopoverMenu, PopoverMenuHandle,
PopoverTrigger, RenderOnce, Window, px,
FluentBuilder as _, IntoElement, PopoverMenu, PopoverMenuHandle, PopoverTrigger, prelude::*,
};
use crate::{Picker, PickerDelegate};
@@ -19,6 +19,7 @@ where
tooltip: TT,
handle: Option<PopoverMenuHandle<Picker<P>>>,
anchor: Corner,
offset: Option<Point<Pixels>>,
_subscriptions: Vec<Subscription>,
}
@@ -43,6 +44,10 @@ where
trigger,
tooltip,
handle: None,
offset: Some(Point {
x: px(0.0),
y: px(-2.0),
}),
anchor,
}
}
@@ -51,6 +56,11 @@ where
self.handle = Some(handle);
self
}
pub fn offset(mut self, offset: Point<Pixels>) -> Self {
self.offset = Some(offset);
self
}
}
impl<T, TT, P> EventEmitter<DismissEvent> for PickerPopoverMenu<T, TT, P>
@@ -86,9 +96,6 @@ where
.trigger_with_tooltip(self.trigger, self.tooltip)
.anchor(self.anchor)
.when_some(self.handle, |menu, handle| menu.with_handle(handle))
.offset(gpui::Point {
x: px(0.0),
y: px(-2.0),
})
.when_some(self.offset, |menu, offset| menu.offset(offset))
}
}