@@ -1,6 +1,6 @@
use gpui::{AnyElement, Div, StyleRefinement};
use smallvec::SmallVec;
-use ui::{ButtonLike, prelude::*};
+use ui::prelude::*;
#[derive(IntoElement)]
pub struct FeatureUpsell {
@@ -46,21 +46,20 @@ impl FeatureUpsell {
impl RenderOnce for FeatureUpsell {
fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
self.base
- .p_4()
+ .py_2()
+ .px_4()
.justify_between()
- .border_color(cx.theme().colors().border)
- .child(v_flex().overflow_hidden().child(Label::new(self.text)))
+ .flex_wrap()
+ .border_color(cx.theme().colors().border_variant)
+ .child(Label::new(self.text))
.child(h_flex().gap_2().children(self.children).when_some(
self.docs_url,
|el, docs_url| {
el.child(
- ButtonLike::new("open_docs")
- .child(
- h_flex()
- .gap_2()
- .child(Label::new("View docs"))
- .child(Icon::new(IconName::ArrowUpRight)),
- )
+ Button::new("open_docs", "View Documentation")
+ .icon(IconName::ArrowUpRight)
+ .icon_size(IconSize::XSmall)
+ .icon_position(IconPosition::End)
.on_click({
let docs_url = docs_url.clone();
move |_event, _window, cx| {
@@ -165,7 +165,7 @@ fn extension_provides_label(provides: ExtensionProvides) -> &'static str {
ExtensionProvides::Languages => "Languages",
ExtensionProvides::Grammars => "Grammars",
ExtensionProvides::LanguageServers => "Language Servers",
- ExtensionProvides::ContextServers => "Context Servers",
+ ExtensionProvides::ContextServers => "MCP Servers",
ExtensionProvides::SlashCommands => "Slash Commands",
ExtensionProvides::IndexedDocsProviders => "Indexed Docs Providers",
ExtensionProvides::Snippets => "Snippets",
@@ -573,6 +573,7 @@ impl ExtensionsPage {
extension.authors.join(", ")
))
.size(LabelSize::Small)
+ .color(Color::Muted)
.truncate(),
)
.child(Label::new("<>").size(LabelSize::Small)),
@@ -594,7 +595,6 @@ impl ExtensionsPage {
)
.icon_color(Color::Accent)
.icon_size(IconSize::Small)
- .style(ButtonStyle::Filled)
.on_click(cx.listener({
let repository_url = repository_url.clone();
move |_, _, _, cx| {
@@ -701,6 +701,7 @@ impl ExtensionsPage {
extension.manifest.authors.join(", ")
))
.size(LabelSize::Small)
+ .color(Color::Muted)
.truncate(),
)
.child(
@@ -731,7 +732,6 @@ impl ExtensionsPage {
)
.icon_color(Color::Accent)
.icon_size(IconSize::Small)
- .style(ButtonStyle::Filled)
.on_click(cx.listener({
let repository_url = repository_url.clone();
move |_, _, _, cx| {
@@ -751,8 +751,7 @@ impl ExtensionsPage {
IconName::Ellipsis,
)
.icon_color(Color::Accent)
- .icon_size(IconSize::Small)
- .style(ButtonStyle::Filled),
+ .icon_size(IconSize::Small),
)
.menu(move |window, cx| {
Some(Self::render_remote_extension_context_menu(
@@ -950,19 +949,20 @@ impl ExtensionsPage {
cx.theme().colors().border
};
- h_flex().w_full().gap_2().key_context(key_context).child(
- h_flex()
- .flex_1()
- .px_2()
- .py_1()
- .gap_2()
- .border_1()
- .border_color(editor_border)
- .min_w(rems_from_px(384.))
- .rounded_lg()
- .child(Icon::new(IconName::MagnifyingGlass))
- .child(self.render_text_input(&self.query_editor, cx)),
- )
+ h_flex()
+ .key_context(key_context)
+ .h_8()
+ .flex_1()
+ .min_w(rems_from_px(384.))
+ .pl_1p5()
+ .pr_2()
+ .py_1()
+ .gap_2()
+ .border_1()
+ .border_color(editor_border)
+ .rounded_lg()
+ .child(Icon::new(IconName::MagnifyingGlass).color(Color::Muted))
+ .child(self.render_text_input(&self.query_editor, cx))
}
fn render_text_input(
@@ -1193,52 +1193,6 @@ impl ExtensionsPage {
upsell.when(ix < upsells_count, |upsell| upsell.border_b_1())
}))
}
-
- fn build_extension_provides_filter_menu(
- &self,
- window: &mut Window,
- cx: &mut Context<Self>,
- ) -> Entity<ContextMenu> {
- let this = cx.entity();
- ContextMenu::build(window, cx, |mut menu, _window, _cx| {
- menu = menu.header("Extension Category").toggleable_entry(
- "All",
- self.provides_filter.is_none(),
- IconPosition::End,
- None,
- {
- let this = this.clone();
- move |_window, cx| {
- this.update(cx, |this, cx| {
- this.change_provides_filter(None, cx);
- });
- }
- },
- );
-
- for provides in ExtensionProvides::iter() {
- let label = extension_provides_label(provides);
-
- menu = menu.toggleable_entry(
- label,
- self.provides_filter == Some(provides),
- IconPosition::End,
- None,
- {
- let this = this.clone();
- move |_window, cx| {
- this.update(cx, |this, cx| {
- this.change_provides_filter(Some(provides), cx);
- this.provides_filter = Some(provides);
- });
- }
- },
- )
- }
-
- menu
- })
- }
}
impl Render for ExtensionsPage {
@@ -1249,9 +1203,8 @@ impl Render for ExtensionsPage {
.child(
v_flex()
.gap_4()
- .p_4()
- .border_b_1()
- .border_color(cx.theme().colors().border)
+ .pt_4()
+ .px_4()
.bg(cx.theme().colors().editor_background)
.child(
h_flex()
@@ -1271,29 +1224,9 @@ impl Render for ExtensionsPage {
.child(
h_flex()
.w_full()
- .gap_2()
- .justify_between()
- .child(h_flex().gap_2().child(self.render_search(cx)).child({
- let this = cx.entity().clone();
- PopoverMenu::new("extension-provides-filter")
- .menu(move |window, cx| {
- Some(this.update(cx, |this, cx| {
- this.build_extension_provides_filter_menu(window, cx)
- }))
- })
- .trigger_with_tooltip(
- Button::new(
- "extension-provides-filter-button",
- self.provides_filter
- .map(extension_provides_label)
- .unwrap_or("All"),
- )
- .icon(IconName::Filter)
- .icon_position(IconPosition::Start),
- Tooltip::text("Filter extensions by category"),
- )
- .anchor(gpui::Corner::TopLeft)
- }))
+ .gap_4()
+ .flex_wrap()
+ .child(self.render_search(cx))
.child(
h_flex()
.child(
@@ -1343,6 +1276,47 @@ impl Render for ExtensionsPage {
),
),
)
+ .child(
+ h_flex()
+ .id("filter-row")
+ .gap_2()
+ .py_2p5()
+ .px_4()
+ .border_b_1()
+ .border_color(cx.theme().colors().border_variant)
+ .overflow_x_scroll()
+ .child(
+ Button::new("filter-all-categories", "All")
+ .when(self.provides_filter.is_none(), |button| {
+ button.style(ButtonStyle::Filled)
+ })
+ .when(self.provides_filter.is_some(), |button| {
+ button.style(ButtonStyle::Subtle)
+ })
+ .toggle_state(self.provides_filter.is_none())
+ .on_click(cx.listener(|this, _event, _, cx| {
+ this.change_provides_filter(None, cx);
+ })),
+ )
+ .children(ExtensionProvides::iter().map(|provides| {
+ let label = extension_provides_label(provides);
+ Button::new(
+ SharedString::from(format!("filter-category-{}", label)),
+ label,
+ )
+ .style(if self.provides_filter == Some(provides) {
+ ButtonStyle::Filled
+ } else {
+ ButtonStyle::Subtle
+ })
+ .toggle_state(self.provides_filter == Some(provides))
+ .on_click({
+ cx.listener(move |this, _event, _, cx| {
+ this.change_provides_filter(Some(provides), cx);
+ })
+ })
+ })),
+ )
.child(self.render_feature_upsells(cx))
.child(
v_flex()