From 912b396e58bf3523276ea2b0465757986895f0a4 Mon Sep 17 00:00:00 2001 From: Danilo Leal <67129314+danilo-leal@users.noreply.github.com> Date: Wed, 24 Jul 2024 07:24:54 -0300 Subject: [PATCH] Adjust model selector popover design (#15056) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR mostly refines the model selector popover design by formatting the models names' and adjusting spacing/alignment in the list-related items. The list component changes could've been made in a separate PR but it was also very practical to do it here as I was already in-context. Either way, I'm happy to separate if that's better! One thing I couldn't necessarily figure out, though, is why the order changed (e.g., Anthropic at last ). I wonder if that was because of the separator logic somehow? I'd love guidance here—new to Rust! | Before | After | |--------|--------| | Screenshot 2024-07-23 at 21 02 33 | Screenshot 2024-07-23 at 21 01 45 | --- Release Notes: - N/A --------- Co-authored-by: Marshall Bowers Co-authored-by: Bennet Bo Fenner Co-authored-by: Antonio Co-authored-by: Antonio Scandurra --- crates/assistant/src/assistant_panel.rs | 41 +++- crates/assistant/src/inline_assistant.rs | 104 +++------ crates/assistant/src/model_selector.rs | 217 +++++++++--------- .../src/terminal_inline_assistant.rs | 104 +++------ crates/completion/src/completion.rs | 4 +- crates/language_model/src/language_model.rs | 8 +- .../language_model/src/provider/anthropic.rs | 3 +- crates/language_model/src/provider/cloud.rs | 3 +- crates/language_model/src/provider/ollama.rs | 4 +- crates/language_model/src/registry.rs | 22 +- crates/ui/src/components/list/list_item.rs | 2 +- .../ui/src/components/list/list_separator.rs | 2 +- .../ui/src/components/list/list_sub_header.rs | 2 +- 13 files changed, 219 insertions(+), 297 deletions(-) diff --git a/crates/assistant/src/assistant_panel.rs b/crates/assistant/src/assistant_panel.rs index 43e63953acea35b3918412c9a173fb2977d2524d..c8aa5aacc8e1b6e05b9c7277cc3a24e6824833e7 100644 --- a/crates/assistant/src/assistant_panel.rs +++ b/crates/assistant/src/assistant_panel.rs @@ -2630,10 +2630,43 @@ impl Render for ContextEditorToolbarItem { }); let right_side = h_flex() .gap_2() - .child(ModelSelector::new( - self.model_selector_menu_handle.clone(), - self.fs.clone(), - )) + .child( + ModelSelector::new( + self.fs.clone(), + ButtonLike::new("active-model") + .style(ButtonStyle::Subtle) + .child( + h_flex() + .w_full() + .gap_0p5() + .child( + div() + .overflow_x_hidden() + .flex_grow() + .whitespace_nowrap() + .child( + Label::new( + LanguageModelCompletionProvider::read_global(cx) + .active_model() + .map(|model| model.name().0) + .unwrap_or_else(|| "No model selected".into()), + ) + .size(LabelSize::Small) + .color(Color::Muted), + ), + ) + .child( + Icon::new(IconName::ChevronDown) + .color(Color::Muted) + .size(IconSize::XSmall), + ), + ) + .tooltip(move |cx| { + Tooltip::for_action("Change Model", &ToggleModelSelector, cx) + }), + ) + .with_handle(self.model_selector_menu_handle.clone()), + ) .children(self.render_remaining_tokens(cx)) .child(self.render_inject_context_menu(cx)); diff --git a/crates/assistant/src/inline_assistant.rs b/crates/assistant/src/inline_assistant.rs index 39d66e8100b9ee29ba029da2abffd323b3eef3ec..2744ee9248b694e6d6e42a33e104d96ddf5775a7 100644 --- a/crates/assistant/src/inline_assistant.rs +++ b/crates/assistant/src/inline_assistant.rs @@ -1,6 +1,6 @@ use crate::{ - assistant_settings::AssistantSettings, humanize_token_count, prompts::generate_content_prompt, - AssistantPanel, AssistantPanelEvent, Hunk, LanguageModelCompletionProvider, StreamingDiff, + humanize_token_count, prompts::generate_content_prompt, AssistantPanel, AssistantPanelEvent, + Hunk, LanguageModelCompletionProvider, ModelSelector, StreamingDiff, }; use anyhow::{anyhow, Context as _, Result}; use client::telemetry::Telemetry; @@ -27,13 +27,11 @@ use gpui::{ WindowContext, }; use language::{Buffer, Point, Selection, TransactionId}; -use language_model::{ - LanguageModelRegistry, LanguageModelRequest, LanguageModelRequestMessage, Role, -}; +use language_model::{LanguageModelRequest, LanguageModelRequestMessage, Role}; use multi_buffer::MultiBufferRow; use parking_lot::Mutex; use rope::Rope; -use settings::{update_settings_file, Settings}; +use settings::Settings; use similar::TextDiff; use smol::future::FutureExt; use std::{ @@ -47,7 +45,7 @@ use std::{ time::{Duration, Instant}, }; use theme::ThemeSettings; -use ui::{prelude::*, ContextMenu, IconButtonShape, PopoverMenu, Tooltip}; +use ui::{prelude::*, IconButtonShape, Tooltip}; use util::RangeExt; use workspace::{notifications::NotificationId, Toast, Workspace}; @@ -1325,8 +1323,6 @@ impl EventEmitter for PromptEditor {} impl Render for PromptEditor { fn render(&mut self, cx: &mut ViewContext) -> impl IntoElement { let gutter_dimensions = *self.gutter_dimensions.lock(); - let fs = self.fs.clone(); - let buttons = match &self.codegen.read(cx).status { CodegenStatus::Idle => { vec![ @@ -1427,74 +1423,27 @@ impl Render for PromptEditor { .w(gutter_dimensions.full_width() + (gutter_dimensions.margin / 2.0)) .justify_center() .gap_2() - .child( - PopoverMenu::new("model-switcher") - .menu(move |cx| { - ContextMenu::build(cx, |mut menu, cx| { - for available_model in - LanguageModelRegistry::read_global(cx).available_models(cx) - { - menu = menu.custom_entry( - { - let model_name = available_model.name().0.clone(); - let provider = - available_model.provider_id().0.clone(); - move |_| { - h_flex() - .w_full() - .justify_between() - .child(Label::new(model_name.clone())) - .child( - div().ml_4().child( - Label::new(provider.clone()) - .color(Color::Muted), - ), - ) - .into_any() - } - }, - { - let fs = fs.clone(); - let model = available_model.clone(); - move |cx| { - let model = model.clone(); - update_settings_file::( - fs.clone(), - cx, - move |settings, _| { - settings.set_model(model) - }, - ); - } - }, - ); - } - menu - }) - .into() - }) - .trigger( - IconButton::new("context", IconName::Settings) - .shape(IconButtonShape::Square) - .icon_size(IconSize::Small) - .icon_color(Color::Muted) - .tooltip(move |cx| { - Tooltip::with_meta( - format!( - "Using {}", - LanguageModelCompletionProvider::read_global(cx) - .active_model() - .map(|model| model.name().0) - .unwrap_or_else(|| "No model selected".into()), - ), - None, - "Change Model", - cx, - ) - }), - ) - .anchor(gpui::AnchorCorner::BottomRight), - ) + .child(ModelSelector::new( + self.fs.clone(), + IconButton::new("context", IconName::Settings) + .shape(IconButtonShape::Square) + .icon_size(IconSize::Small) + .icon_color(Color::Muted) + .tooltip(move |cx| { + Tooltip::with_meta( + format!( + "Using {}", + LanguageModelCompletionProvider::read_global(cx) + .active_model() + .map(|model| model.name().0) + .unwrap_or_else(|| "No model selected".into()), + ), + None, + "Change Model", + cx, + ) + }), + )) .children( if let CodegenStatus::Error(error) = &self.codegen.read(cx).status { let error_message = SharedString::from(error.to_string()); @@ -2625,6 +2574,7 @@ mod tests { language_settings, tree_sitter_rust, Buffer, Language, LanguageConfig, LanguageMatcher, Point, }; + use language_model::LanguageModelRegistry; use rand::prelude::*; use serde::Serialize; use settings::SettingsStore; diff --git a/crates/assistant/src/model_selector.rs b/crates/assistant/src/model_selector.rs index 3d628497b708e1091d896b1db24a3d44c552f696..3847c7b29f5ed1c9fe3b2cc6c58caf665a6307ee 100644 --- a/crates/assistant/src/model_selector.rs +++ b/crates/assistant/src/model_selector.rs @@ -1,127 +1,128 @@ use std::sync::Arc; -use crate::{ - assistant_settings::AssistantSettings, LanguageModelCompletionProvider, ToggleModelSelector, -}; +use crate::{assistant_settings::AssistantSettings, LanguageModelCompletionProvider}; use fs::Fs; use language_model::LanguageModelRegistry; use settings::update_settings_file; -use ui::{prelude::*, ButtonLike, ContextMenu, PopoverMenu, PopoverMenuHandle, Tooltip}; +use ui::{prelude::*, ContextMenu, PopoverMenu, PopoverMenuHandle, PopoverTrigger}; #[derive(IntoElement)] -pub struct ModelSelector { - handle: PopoverMenuHandle, +pub struct ModelSelector { + handle: Option>, fs: Arc, + trigger: T, } -impl ModelSelector { - pub fn new(handle: PopoverMenuHandle, fs: Arc) -> Self { - ModelSelector { handle, fs } +impl ModelSelector { + pub fn new(fs: Arc, trigger: T) -> Self { + ModelSelector { + handle: None, + fs, + trigger, + } + } + + pub fn with_handle(mut self, handle: PopoverMenuHandle) -> Self { + self.handle = Some(handle); + self } } -impl RenderOnce for ModelSelector { - fn render(self, cx: &mut WindowContext) -> impl IntoElement { - PopoverMenu::new("model-switcher") - .with_handle(self.handle) - .menu(move |cx| { - ContextMenu::build(cx, |mut menu, cx| { - for (provider, available_models) in LanguageModelRegistry::global(cx) - .read(cx) - .available_models_grouped_by_provider(cx) - { - menu = menu.header(provider.0.clone()); +impl RenderOnce for ModelSelector { + fn render(self, _: &mut WindowContext) -> impl IntoElement { + let mut menu = PopoverMenu::new("model-switcher"); + if let Some(handle) = self.handle { + menu = menu.with_handle(handle); + } - if available_models.is_empty() { - menu = menu.custom_entry( - { - move |_| { - h_flex() - .w_full() - .gap_1() - .child(Icon::new(IconName::Settings)) - .child(Label::new("Configure")) - .into_any() - } - }, - { - let provider = provider.clone(); - move |cx| { - LanguageModelCompletionProvider::global(cx).update( - cx, - |completion_provider, cx| { - completion_provider - .set_active_provider(provider.clone(), cx) - }, - ); - } - }, - ); - } + menu.menu(move |cx| { + ContextMenu::build(cx, |mut menu, cx| { + for (index, provider) in LanguageModelRegistry::global(cx) + .read(cx) + .providers() + .enumerate() + { + if index > 0 { + menu = menu.separator(); + } + menu = menu.header(provider.name().0); - for available_model in available_models { - menu = menu.custom_entry( - { - let model_name = available_model.name().0.clone(); - move |_| { - h_flex() - .w_full() - .child(Label::new(model_name.clone())) - .into_any() - } - }, - { - let fs = self.fs.clone(); - let model = available_model.clone(); - move |cx| { - let model = model.clone(); - update_settings_file::( - fs.clone(), - cx, - move |settings, _| settings.set_model(model), - ); - } - }, - ); - } + let available_models = provider.provided_models(cx); + if available_models.is_empty() { + menu = menu.custom_entry( + { + move |_| { + h_flex() + .w_full() + .gap_1() + .child(Icon::new(IconName::Settings)) + .child(Label::new("Configure")) + .into_any() + } + }, + { + let provider = provider.id(); + move |cx| { + LanguageModelCompletionProvider::global(cx).update( + cx, + |completion_provider, cx| { + completion_provider + .set_active_provider(provider.clone(), cx) + }, + ); + } + }, + ); } - menu - }) - .into() - }) - .trigger( - ButtonLike::new("active-model") - .style(ButtonStyle::Subtle) - .child( - h_flex() - .w_full() - .gap_0p5() - .child( - div() - .overflow_x_hidden() - .flex_grow() - .whitespace_nowrap() - .child( - Label::new( - LanguageModelCompletionProvider::read_global(cx) - .active_model() - .map(|model| model.name().0) - .unwrap_or_else(|| "No model selected".into()), + + let selected_model = LanguageModelCompletionProvider::read_global(cx) + .active_model() + .map(|m| m.id()); + let selected_provider = LanguageModelCompletionProvider::read_global(cx) + .active_provider() + .map(|m| m.id()); + + for available_model in available_models { + menu = menu.custom_entry( + { + let id = available_model.id(); + let provider_id = available_model.provider_id(); + let model_name = available_model.name().0.clone(); + let selected_model = selected_model.clone(); + let selected_provider = selected_provider.clone(); + move |_| { + h_flex() + .w_full() + .justify_between() + .child(Label::new(model_name.clone())) + .when( + selected_model.as_ref() == Some(&id) + && selected_provider.as_ref() == Some(&provider_id), + |this| this.child(Icon::new(IconName::Check)), ) - .size(LabelSize::Small) - .color(Color::Muted), - ), - ) - .child( - Icon::new(IconName::ChevronDown) - .color(Color::Muted) - .size(IconSize::XSmall), - ), - ) - .tooltip(move |cx| { - Tooltip::for_action("Change Model", &ToggleModelSelector, cx) - }), - ) - .attach(gpui::AnchorCorner::BottomLeft) + .into_any() + } + }, + { + let fs = self.fs.clone(); + let model = available_model.clone(); + move |cx| { + let model = model.clone(); + update_settings_file::( + fs.clone(), + cx, + move |settings, _| settings.set_model(model), + ); + } + }, + ); + } + } + menu + }) + .into() + }) + .trigger(self.trigger) + .attach(gpui::AnchorCorner::BottomLeft) } } diff --git a/crates/assistant/src/terminal_inline_assistant.rs b/crates/assistant/src/terminal_inline_assistant.rs index 5a391f8ac495db59a8e5bd53108d69f4ea028995..b2314fc5328616a925da5aca0c4ded7334a87d28 100644 --- a/crates/assistant/src/terminal_inline_assistant.rs +++ b/crates/assistant/src/terminal_inline_assistant.rs @@ -1,7 +1,6 @@ use crate::{ - assistant_settings::AssistantSettings, humanize_token_count, - prompts::generate_terminal_assistant_prompt, AssistantPanel, AssistantPanelEvent, - LanguageModelCompletionProvider, + humanize_token_count, prompts::generate_terminal_assistant_prompt, AssistantPanel, + AssistantPanelEvent, LanguageModelCompletionProvider, ModelSelector, }; use anyhow::{Context as _, Result}; use client::telemetry::Telemetry; @@ -17,10 +16,8 @@ use gpui::{ Subscription, Task, TextStyle, UpdateGlobal, View, WeakView, }; use language::Buffer; -use language_model::{ - LanguageModelRegistry, LanguageModelRequest, LanguageModelRequestMessage, Role, -}; -use settings::{update_settings_file, Settings}; +use language_model::{LanguageModelRequest, LanguageModelRequestMessage, Role}; +use settings::Settings; use std::{ cmp, sync::Arc, @@ -29,7 +26,7 @@ use std::{ use terminal::Terminal; use terminal_view::TerminalView; use theme::ThemeSettings; -use ui::{prelude::*, ContextMenu, IconButtonShape, PopoverMenu, Tooltip}; +use ui::{prelude::*, IconButtonShape, Tooltip}; use util::ResultExt; use workspace::{notifications::NotificationId, Toast, Workspace}; @@ -450,8 +447,6 @@ impl EventEmitter for PromptEditor {} impl Render for PromptEditor { fn render(&mut self, cx: &mut ViewContext) -> impl IntoElement { - let fs = self.fs.clone(); - let buttons = match &self.codegen.read(cx).status { CodegenStatus::Idle => { vec![ @@ -554,74 +549,27 @@ impl Render for PromptEditor { .w_12() .justify_center() .gap_2() - .child( - PopoverMenu::new("model-switcher") - .menu(move |cx| { - ContextMenu::build(cx, |mut menu, cx| { - for available_model in - LanguageModelRegistry::read_global(cx).available_models(cx) - { - menu = menu.custom_entry( - { - let model_name = available_model.name().0.clone(); - let provider = - available_model.provider_id().0.clone(); - move |_| { - h_flex() - .w_full() - .justify_between() - .child(Label::new(model_name.clone())) - .child( - div().ml_4().child( - Label::new(provider.clone()) - .color(Color::Muted), - ), - ) - .into_any() - } - }, - { - let fs = fs.clone(); - let model = available_model.clone(); - move |cx| { - let model = model.clone(); - update_settings_file::( - fs.clone(), - cx, - move |settings, _| { - settings.set_model(model) - }, - ); - } - }, - ); - } - menu - }) - .into() - }) - .trigger( - IconButton::new("context", IconName::Settings) - .shape(IconButtonShape::Square) - .icon_size(IconSize::Small) - .icon_color(Color::Muted) - .tooltip(move |cx| { - Tooltip::with_meta( - format!( - "Using {}", - LanguageModelCompletionProvider::read_global(cx) - .active_model() - .map(|model| model.name().0) - .unwrap_or_else(|| "No model selected".into()) - ), - None, - "Change Model", - cx, - ) - }), - ) - .anchor(gpui::AnchorCorner::BottomRight), - ) + .child(ModelSelector::new( + self.fs.clone(), + IconButton::new("context", IconName::Settings) + .shape(IconButtonShape::Square) + .icon_size(IconSize::Small) + .icon_color(Color::Muted) + .tooltip(move |cx| { + Tooltip::with_meta( + format!( + "Using {}", + LanguageModelCompletionProvider::read_global(cx) + .active_model() + .map(|model| model.name().0) + .unwrap_or_else(|| "No model selected".into()), + ), + None, + "Change Model", + cx, + ) + }), + )) .children( if let CodegenStatus::Error(error) = &self.codegen.read(cx).status { let error_message = SharedString::from(error.to_string()); diff --git a/crates/completion/src/completion.rs b/crates/completion/src/completion.rs index 22179907d07352b88697fae855f5b5aa571c49c5..c817b79ff36d9b5a120bd9105d7694547c9c7f53 100644 --- a/crates/completion/src/completion.rs +++ b/crates/completion/src/completion.rs @@ -89,10 +89,10 @@ impl LanguageModelCompletionProvider { pub fn set_active_provider( &mut self, - provider_name: LanguageModelProviderId, + provider_id: LanguageModelProviderId, cx: &mut ModelContext, ) { - self.active_provider = LanguageModelRegistry::read_global(cx).provider(&provider_name); + self.active_provider = LanguageModelRegistry::read_global(cx).provider(&provider_id); self.active_model = None; cx.notify(); } diff --git a/crates/language_model/src/language_model.rs b/crates/language_model/src/language_model.rs index 4eb3f8a32be492035ec7efc2a6456fe54a37cb89..91edcab6f544fce33d56ca5deea0cdcceadb0135 100644 --- a/crates/language_model/src/language_model.rs +++ b/crates/language_model/src/language_model.rs @@ -59,16 +59,16 @@ pub trait LanguageModelProviderState: 'static { fn subscribe(&self, cx: &mut gpui::ModelContext) -> Option; } -#[derive(Clone, Eq, PartialEq, Hash, Debug)] +#[derive(Clone, Eq, PartialEq, Hash, Debug, Ord, PartialOrd)] pub struct LanguageModelId(pub SharedString); -#[derive(Clone, Eq, PartialEq, Hash, Debug)] +#[derive(Clone, Eq, PartialEq, Hash, Debug, Ord, PartialOrd)] pub struct LanguageModelName(pub SharedString); -#[derive(Clone, Eq, PartialEq, Hash, Debug)] +#[derive(Clone, Eq, PartialEq, Hash, Debug, Ord, PartialOrd)] pub struct LanguageModelProviderId(pub SharedString); -#[derive(Clone, Eq, PartialEq, Hash, Debug)] +#[derive(Clone, Eq, PartialEq, Hash, Debug, Ord, PartialOrd)] pub struct LanguageModelProviderName(pub SharedString); impl From for LanguageModelId { diff --git a/crates/language_model/src/provider/anthropic.rs b/crates/language_model/src/provider/anthropic.rs index 093cc25057d2c682a6dc84c6f34b59b6416d8d24..7743ec6128164da4dd9dec3864b91e93fc38d58a 100644 --- a/crates/language_model/src/provider/anthropic.rs +++ b/crates/language_model/src/provider/anthropic.rs @@ -1,5 +1,6 @@ use anthropic::{stream_completion, Request, RequestMessage}; use anyhow::{anyhow, Result}; +use collections::BTreeMap; use editor::{Editor, EditorElement, EditorStyle}; use futures::{future::BoxFuture, stream::BoxStream, FutureExt, StreamExt}; use gpui::{ @@ -8,7 +9,7 @@ use gpui::{ }; use http_client::HttpClient; use settings::{Settings, SettingsStore}; -use std::{collections::BTreeMap, sync::Arc, time::Duration}; +use std::{sync::Arc, time::Duration}; use strum::IntoEnumIterator; use theme::ThemeSettings; use ui::prelude::*; diff --git a/crates/language_model/src/provider/cloud.rs b/crates/language_model/src/provider/cloud.rs index c0cbdbdf1d9c78dfea97295ec712ff4d57796bd0..1cd8b99e98acc661939821b115cc3fda53ded86d 100644 --- a/crates/language_model/src/provider/cloud.rs +++ b/crates/language_model/src/provider/cloud.rs @@ -6,10 +6,11 @@ use crate::{ }; use anyhow::Result; use client::Client; +use collections::BTreeMap; use futures::{future::BoxFuture, stream::BoxStream, FutureExt, StreamExt, TryFutureExt}; use gpui::{AnyView, AppContext, AsyncAppContext, Subscription, Task}; use settings::{Settings, SettingsStore}; -use std::{collections::BTreeMap, sync::Arc}; +use std::sync::Arc; use strum::IntoEnumIterator; use ui::prelude::*; diff --git a/crates/language_model/src/provider/ollama.rs b/crates/language_model/src/provider/ollama.rs index 3b6a3fb3b33fd43d9b7bc99f3d90181eb29a7a6e..c1896aafe9c8ca4588beddc31d0cb7772b50709d 100644 --- a/crates/language_model/src/provider/ollama.rs +++ b/crates/language_model/src/provider/ollama.rs @@ -75,12 +75,12 @@ impl OllamaLanguageModelProvider { http_client, available_models: Default::default(), _subscription: cx.observe_global::(|this: &mut State, cx| { - this.fetch_models(cx).detach_and_log_err(cx); + this.fetch_models(cx).detach(); cx.notify(); }), }), }; - this.fetch_models(cx).detach_and_log_err(cx); + this.fetch_models(cx).detach(); this } diff --git a/crates/language_model/src/registry.rs b/crates/language_model/src/registry.rs index 9c92f912bd234363956edff290cc946fe1127745..e787f5f7e75c85f3fbda6570a7db5deddaaffd06 100644 --- a/crates/language_model/src/registry.rs +++ b/crates/language_model/src/registry.rs @@ -1,5 +1,5 @@ use client::Client; -use collections::HashMap; +use collections::BTreeMap; use gpui::{AppContext, Global, Model, ModelContext}; use std::sync::Arc; use ui::Context; @@ -65,7 +65,7 @@ impl Global for GlobalLanguageModelRegistry {} #[derive(Default)] pub struct LanguageModelRegistry { - providers: HashMap>, + providers: BTreeMap>, } impl LanguageModelRegistry { @@ -114,10 +114,8 @@ impl LanguageModelRegistry { } } - pub fn providers( - &self, - ) -> impl Iterator)> { - self.providers.iter() + pub fn providers(&self) -> impl Iterator> { + self.providers.values() } pub fn available_models(&self, cx: &AppContext) -> Vec> { @@ -127,16 +125,6 @@ impl LanguageModelRegistry { .collect() } - pub fn available_models_grouped_by_provider( - &self, - cx: &AppContext, - ) -> HashMap>> { - self.providers - .iter() - .map(|(name, provider)| (name.clone(), provider.provided_models(cx))) - .collect() - } - pub fn provider( &self, name: &LanguageModelProviderId, @@ -160,7 +148,7 @@ mod tests { let providers = registry.read(cx).providers().collect::>(); assert_eq!(providers.len(), 1); - assert_eq!(providers[0].0, &crate::provider::fake::provider_id()); + assert_eq!(providers[0].id(), crate::provider::fake::provider_id()); registry.update(cx, |registry, cx| { registry.unregister_provider(&crate::provider::fake::provider_id(), cx); diff --git a/crates/ui/src/components/list/list_item.rs b/crates/ui/src/components/list/list_item.rs index 3fcd20f5239d2bdbfe151698508b41b8ee7c4ce4..11ae1808f994fb331f63d359a6b70de5cf61d839 100644 --- a/crates/ui/src/components/list/list_item.rs +++ b/crates/ui/src/components/list/list_item.rs @@ -185,7 +185,7 @@ impl RenderOnce for ListItem { .w_full() .relative() .gap_1() - .px_2() + .px_1p5() .map(|this| match self.spacing { ListItemSpacing::Dense => this, ListItemSpacing::Sparse => this.py_1(), diff --git a/crates/ui/src/components/list/list_separator.rs b/crates/ui/src/components/list/list_separator.rs index 59b85be5ce4a149ac9b3793cd029f8d420575f7b..b53dc7a0433d6be175ca2897297ec5ab32986d8d 100644 --- a/crates/ui/src/components/list/list_separator.rs +++ b/crates/ui/src/components/list/list_separator.rs @@ -8,7 +8,7 @@ impl RenderOnce for ListSeparator { div() .h_px() .w_full() - .my_1() + .my_1p5() .bg(cx.theme().colors().border_variant) } } diff --git a/crates/ui/src/components/list/list_sub_header.rs b/crates/ui/src/components/list/list_sub_header.rs index eab9cbf0f0a9eb95900432dbf306ba171c812bb0..2aa9387129beb20a040fbbe04f6bbb4cf3c816ff 100644 --- a/crates/ui/src/components/list/list_sub_header.rs +++ b/crates/ui/src/components/list/list_sub_header.rs @@ -39,7 +39,7 @@ impl Selectable for ListSubHeader { impl RenderOnce for ListSubHeader { fn render(self, cx: &mut WindowContext) -> impl IntoElement { - h_flex().flex_1().w_full().relative().py_1().child( + h_flex().flex_1().w_full().relative().pb_1().px_0p5().child( div() .h_6() .when(self.inset, |this| this.px_2())