From 2764c51af16e5bfead0c6c4870e71fe3605ba8fe Mon Sep 17 00:00:00 2001
From: Danilo Leal <67129314+danilo-leal@users.noreply.github.com>
Date: Tue, 21 Oct 2025 13:55:42 -0300
Subject: [PATCH] extensions_ui: Increase affordance of download button in
cards (#40795)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Hopefully, this will make the install/configure/uninstall buttons in the
right stand out a bit more and make their presence a bit more obvious
for newcomers.
| Before | After |
|--------|--------|
|
|
|
Release Notes:
- Increased affordance of the download button in each extension card in
the extensions page.
---
.../src/components/extension_card.rs | 9 ++-
crates/extensions_ui/src/extensions_ui.rs | 71 ++++++++++++-------
2 files changed, 49 insertions(+), 31 deletions(-)
diff --git a/crates/extensions_ui/src/components/extension_card.rs b/crates/extensions_ui/src/components/extension_card.rs
index abdd32fee99cd056e9fece60a2ff7646f55cd264..524f90c7f0e32c0cc60143070c10288c441089e9 100644
--- a/crates/extensions_ui/src/components/extension_card.rs
+++ b/crates/extensions_ui/src/components/extension_card.rs
@@ -32,14 +32,14 @@ impl RenderOnce for ExtensionCard {
fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
div().w_full().child(
v_flex()
+ .mt_4()
.w_full()
- .h(rems(7.))
+ .h(rems_from_px(110.))
.p_3()
- .mt_4()
.gap_2()
- .bg(cx.theme().colors().elevated_surface_background)
+ .bg(cx.theme().colors().elevated_surface_background.opacity(0.5))
.border_1()
- .border_color(cx.theme().colors().border)
+ .border_color(cx.theme().colors().border_variant)
.rounded_md()
.children(self.children)
.when(self.overridden_by_dev_extension, |card| {
@@ -51,7 +51,6 @@ impl RenderOnce for ExtensionCard {
.block_mouse_except_scroll()
.cursor_default()
.size_full()
- .items_center()
.justify_center()
.bg(cx.theme().colors().elevated_surface_background.alpha(0.8))
.child(Label::new("Overridden by dev extension.")),
diff --git a/crates/extensions_ui/src/extensions_ui.rs b/crates/extensions_ui/src/extensions_ui.rs
index dc40bad4e0476f5e714aa24fa3ef4d618d2bdcc9..8ddf9841a12e1313f105b76cacdae2b571bb1fd0 100644
--- a/crates/extensions_ui/src/extensions_ui.rs
+++ b/crates/extensions_ui/src/extensions_ui.rs
@@ -13,8 +13,8 @@ use editor::{Editor, EditorElement, EditorStyle};
use extension_host::{ExtensionManifest, ExtensionOperation, ExtensionStore};
use fuzzy::{StringMatchCandidate, match_strings};
use gpui::{
- Action, App, ClipboardItem, Context, Entity, EventEmitter, Flatten, Focusable,
- InteractiveElement, KeyContext, ParentElement, Render, Styled, Task, TextStyle,
+ Action, App, ClipboardItem, Context, Corner, Entity, EventEmitter, Flatten, Focusable,
+ InteractiveElement, KeyContext, ParentElement, Point, Render, Styled, Task, TextStyle,
UniformListScrollHandle, WeakEntity, Window, actions, point, uniform_list,
};
use num_format::{Locale, ToFormattedString};
@@ -727,7 +727,7 @@ impl ExtensionsPage {
.gap_2()
.child(
Headline::new(extension.manifest.name.clone())
- .size(HeadlineSize::Medium),
+ .size(HeadlineSize::Small),
)
.child(Headline::new(format!("v{version}")).size(HeadlineSize::XSmall))
.children(
@@ -777,20 +777,12 @@ impl ExtensionsPage {
h_flex()
.gap_2()
.justify_between()
- .child(
- Label::new(format!(
- "{}: {}",
- if extension.manifest.authors.len() > 1 {
- "Authors"
- } else {
- "Author"
- },
- extension.manifest.authors.join(", ")
- ))
- .size(LabelSize::Small)
- .color(Color::Muted)
- .truncate(),
- )
+ .children(extension.manifest.description.as_ref().map(|description| {
+ Label::new(description.clone())
+ .size(LabelSize::Small)
+ .color(Color::Default)
+ .truncate()
+ }))
.child(
Label::new(format!(
"Downloads: {}",
@@ -803,21 +795,29 @@ impl ExtensionsPage {
h_flex()
.gap_2()
.justify_between()
- .children(extension.manifest.description.as_ref().map(|description| {
- Label::new(description.clone())
- .size(LabelSize::Small)
- .color(Color::Default)
- .truncate()
- }))
.child(
h_flex()
- .gap_2()
+ .gap_1()
+ .child(
+ Icon::new(IconName::Person)
+ .size(IconSize::XSmall)
+ .color(Color::Muted),
+ )
+ .child(
+ Label::new(extension.manifest.authors.join(", "))
+ .size(LabelSize::Small)
+ .color(Color::Muted)
+ .truncate(),
+ ),
+ )
+ .child(
+ h_flex()
+ .gap_1()
.child(
IconButton::new(
SharedString::from(format!("repository-{}", extension.id)),
IconName::Github,
)
- .icon_color(Color::Accent)
.icon_size(IconSize::Small)
.on_click(cx.listener({
let repository_url = repository_url.clone();
@@ -837,9 +837,13 @@ impl ExtensionsPage {
SharedString::from(format!("more-{}", extension.id)),
IconName::Ellipsis,
)
- .icon_color(Color::Accent)
.icon_size(IconSize::Small),
)
+ .anchor(Corner::TopRight)
+ .offset(Point {
+ x: px(0.0),
+ y: px(2.0),
+ })
.menu(move |window, cx| {
Some(Self::render_remote_extension_context_menu(
&this,
@@ -961,6 +965,11 @@ impl ExtensionsPage {
SharedString::from(extension.id.clone()),
"Install",
)
+ .style(ButtonStyle::Tinted(ui::TintColor::Accent))
+ .icon(IconName::Download)
+ .icon_size(IconSize::Small)
+ .icon_color(Color::Muted)
+ .icon_position(IconPosition::Start)
.on_click({
let extension_id = extension.id.clone();
move |_, _, cx| {
@@ -978,6 +987,11 @@ impl ExtensionsPage {
SharedString::from(extension.id.clone()),
"Install",
)
+ .style(ButtonStyle::Tinted(ui::TintColor::Accent))
+ .icon(IconName::Download)
+ .icon_size(IconSize::Small)
+ .icon_color(Color::Muted)
+ .icon_position(IconPosition::Start)
.disabled(true),
configure: None,
upgrade: None,
@@ -987,6 +1001,7 @@ impl ExtensionsPage {
SharedString::from(extension.id.clone()),
"Uninstall",
)
+ .style(ButtonStyle::OutlinedGhost)
.disabled(true),
configure: is_configurable.then(|| {
Button::new(
@@ -1004,6 +1019,7 @@ impl ExtensionsPage {
SharedString::from(extension.id.clone()),
"Uninstall",
)
+ .style(ButtonStyle::OutlinedGhost)
.on_click({
let extension_id = extension.id.clone();
move |_, _, cx| {
@@ -1020,6 +1036,7 @@ impl ExtensionsPage {
SharedString::from(format!("configure-{}", extension.id)),
"Configure",
)
+ .style(ButtonStyle::OutlinedGhost)
.on_click({
let extension_id = extension.id.clone();
move |_, _, cx| {
@@ -1044,6 +1061,7 @@ impl ExtensionsPage {
} else {
Some(
Button::new(SharedString::from(extension.id.clone()), "Upgrade")
+ .style(ButtonStyle::Tinted(ui::TintColor::Accent))
.when(!is_compatible, |upgrade_button| {
upgrade_button.disabled(true).tooltip({
let version = extension.manifest.version.clone();
@@ -1082,6 +1100,7 @@ impl ExtensionsPage {
SharedString::from(extension.id.clone()),
"Uninstall",
)
+ .style(ButtonStyle::OutlinedGhost)
.disabled(true),
configure: is_configurable.then(|| {
Button::new(