acp: Improve the ACP registry UI (#47788)

Danilo Leal created

This PR adds some UI improvements to the ACP registry UI, already
including the URL for the soon-to-be-released blog post. I'm also
renaming the action to open the page from `zed: agent registry` to `zed:
acp registry`.

Release Notes:

- N/A

Change summary

crates/agent_ui/src/agent_configuration.rs |   2 
crates/agent_ui/src/agent_panel.rs         |   2 
crates/agent_ui/src/agent_registry_ui.rs   | 141 +++++++++++++----------
crates/agent_ui/src/agent_ui.rs            |   2 
crates/extensions_ui/src/extensions_ui.rs  |   2 
crates/zed_actions/src/lib.rs              |   4 
6 files changed, 87 insertions(+), 66 deletions(-)

Detailed changes

crates/agent_ui/src/agent_configuration.rs 🔗

@@ -1001,7 +1001,7 @@ impl AgentConfiguration {
                     Some(ContextMenu::build(window, cx, |menu, _window, _cx| {
                         menu.entry("Install from Registry", None, {
                             |window, cx| {
-                                window.dispatch_action(Box::new(zed_actions::AgentRegistry), cx)
+                                window.dispatch_action(Box::new(zed_actions::AcpRegistry), cx)
                             }
                         })
                         .entry("Add Custom Agent", None, {

crates/agent_ui/src/agent_panel.rs 🔗

@@ -2276,7 +2276,7 @@ impl AgentPanel {
                                     .handler({
                                         move |window, cx| {
                                             window.dispatch_action(
-                                                Box::new(zed_actions::AgentRegistry),
+                                                Box::new(zed_actions::AcpRegistry),
                                                 cx,
                                             )
                                         }

crates/agent_ui/src/agent_registry_ui.rs 🔗

@@ -13,7 +13,7 @@ use project::{AgentRegistryStore, RegistryAgent};
 use settings::{Settings, SettingsStore, update_settings_file};
 use theme::ThemeSettings;
 use ui::{
-    ButtonStyle, Chip, ScrollableHandle, ToggleButtonGroup, ToggleButtonGroupSize,
+    ButtonLink, ButtonStyle, Chip, ScrollableHandle, ToggleButtonGroup, ToggleButtonGroupSize,
     ToggleButtonGroupStyle, ToggleButtonSimple, Tooltip, WithScrollbar, prelude::*,
 };
 use workspace::{
@@ -63,10 +63,10 @@ impl RenderOnce for AgentRegistryCard {
     fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
         div().w_full().child(
             v_flex()
+                .p_3()
                 .mt_4()
                 .w_full()
-                .min_h(rems_from_px(110.))
-                .p_3()
+                .min_h(rems_from_px(86.))
                 .gap_2()
                 .bg(cx.theme().colors().elevated_surface_background.opacity(0.5))
                 .border_1()
@@ -385,15 +385,24 @@ impl AgentRegistryPage {
             self.install_button(agent, install_status, supports_current_platform, cx);
 
         let repository_button = agent.repository().map(|repository| {
-            let repository = repository.clone();
+            let repository_for_tooltip: SharedString = repository.to_string().into();
+            let repository_for_click = repository.to_string();
+
             IconButton::new(
                 SharedString::from(format!("agent-repo-{}", agent.id())),
-                IconName::Link,
+                IconName::Github,
             )
             .icon_size(IconSize::Small)
-            .tooltip(Tooltip::text("Visit agent repository"))
+            .tooltip(move |_, cx| {
+                Tooltip::with_meta(
+                    "Visit Agent Repository",
+                    None,
+                    repository_for_tooltip.clone(),
+                    cx,
+                )
+            })
             .on_click(move |_, _, cx| {
-                cx.open_url(repository.as_ref());
+                cx.open_url(&repository_for_click);
             })
         });
 
@@ -401,23 +410,19 @@ impl AgentRegistryPage {
             .child(
                 h_flex()
                     .justify_between()
-                    .items_start()
                     .child(
-                        h_flex().gap_2().items_center().child(icon).child(
-                            v_flex().gap_0p5().child(
-                                h_flex()
-                                    .gap_2()
-                                    .items_end()
-                                    .child(
-                                        Headline::new(agent.name().clone())
-                                            .size(HeadlineSize::Small),
-                                    )
-                                    .child(
-                                        Headline::new(format!("v{}", agent.version()))
-                                            .size(HeadlineSize::XSmall),
-                                    ),
-                            ),
-                        ),
+                        h_flex()
+                            .gap_2()
+                            .child(icon)
+                            .child(Headline::new(agent.name().clone()).size(HeadlineSize::Small))
+                            .child(Label::new(format!("v{}", agent.version())).color(Color::Muted))
+                            .when(!supports_current_platform, |this| {
+                                this.child(
+                                    Label::new("Not supported on this platform")
+                                        .size(LabelSize::Small)
+                                        .color(Color::Warning),
+                                )
+                            }),
                     )
                     .child(install_button),
             )
@@ -428,28 +433,19 @@ impl AgentRegistryPage {
                     .child(
                         Label::new(agent.description().clone())
                             .size(LabelSize::Small)
-                            .color(Color::Default)
                             .truncate(),
                     )
-                    .when_some(repository_button, |this, button| this.child(button)),
-            )
-            .child(
-                h_flex()
-                    .gap_2()
-                    .justify_between()
                     .child(
-                        Label::new(format!("ID: {}", agent.id()))
-                            .size(LabelSize::Small)
-                            .color(Color::Muted)
-                            .truncate(),
-                    )
-                    .when(!supports_current_platform, |this| {
-                        this.child(
-                            Label::new("Not supported on this platform")
-                                .size(LabelSize::Small)
-                                .color(Color::Warning),
-                        )
-                    }),
+                        h_flex()
+                            .gap_1()
+                            .child(
+                                Label::new(format!("ID: {}", agent.id()))
+                                    .size(LabelSize::Small)
+                                    .color(Color::Muted)
+                                    .truncate(),
+                            )
+                            .when_some(repository_button, |this, button| this.child(button)),
+                    ),
             )
     }
 
@@ -529,29 +525,54 @@ impl AgentRegistryPage {
 
 impl Render for AgentRegistryPage {
     fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
+        let learn_more_url = "https://zed.dev/blog/acp-registry";
+
         v_flex()
             .size_full()
             .bg(cx.theme().colors().editor_background)
             .child(
                 v_flex()
+                    .p_4()
                     .gap_4()
-                    .pt_4()
-                    .px_4()
-                    .bg(cx.theme().colors().editor_background)
+                    .border_b_1()
+                    .border_color(cx.theme().colors().border_variant)
                     .child(
-                        h_flex().w_full().gap_1p5().justify_between().child(
-                            h_flex()
-                                .gap_2()
-                                .items_baseline()
-                                .child(
-                                    Headline::new("ACP Agent Registry").size(HeadlineSize::XLarge),
-                                )
-                                .child(div().id("beta-chip").child(Chip::new("Beta")).tooltip(
-                                    Tooltip::text(
-                                        "The ACP Agent Registry is still in an beta testing phase. For more information, visit https://github.com/agentclientprotocol/registry",
-                                    ),
-                                )),
-                        ),
+                        h_flex()
+                            .w_full()
+                            .gap_1p5()
+                            .justify_between()
+                            .child(
+                                h_flex()
+                                    .id("title")
+                                    .gap_2()
+                                    .child(Headline::new("ACP Registry").size(HeadlineSize::Large))
+                                    .child(Chip::new("Beta"))
+                                    .hoverable_tooltip({
+                                        let learn_more_url = learn_more_url.to_string();
+                                        let tooltip_fn = Tooltip::element(move |_, _| {
+                                            v_flex()
+                                                .gap_1()
+                                                .child(Label::new(
+                                                    "The ACP Registry is still in testing phase.",
+                                                ))
+                                                .child(ButtonLink::new(
+                                                    "Learn more about it",
+                                                    learn_more_url.as_str(),
+                                                ))
+                                                .into_any_element()
+                                        });
+                                        move |window, cx| tooltip_fn(window, cx)
+                                    }),
+                            )
+                            .child(
+                                Button::new("learn-more", "Learn More")
+                                    .style(ButtonStyle::Outlined)
+                                    .size(ButtonSize::Medium)
+                                    .icon(IconName::ArrowUpRight)
+                                    .icon_color(Color::Muted)
+                                    .icon_size(IconSize::Small)
+                                    .on_click(move |_, _, cx| cx.open_url(learn_more_url)),
+                            ),
                     )
                     .child(
                         h_flex()
@@ -635,11 +656,11 @@ impl Item for AgentRegistryPage {
     type Event = ItemEvent;
 
     fn tab_content_text(&self, _detail: usize, _cx: &App) -> SharedString {
-        "ACP Agent Registry".into()
+        "ACP Registry".into()
     }
 
     fn telemetry_event_text(&self) -> Option<&'static str> {
-        Some("ACP Agent Registry Page Opened")
+        Some("ACP Registry Page Opened")
     }
 
     fn show_toolbar(&self) -> bool {

crates/agent_ui/src/agent_ui.rs 🔗

@@ -276,7 +276,7 @@ pub fn init(
     cx.observe_new(|workspace: &mut Workspace, _window, _cx| {
         workspace.register_action(
             move |workspace: &mut Workspace,
-                  _: &zed_actions::AgentRegistry,
+                  _: &zed_actions::AcpRegistry,
                   window: &mut Window,
                   cx: &mut Context<Workspace>| {
                 let existing = workspace

crates/extensions_ui/src/extensions_ui.rs 🔗

@@ -1627,7 +1627,7 @@ impl Render for ExtensionsPage {
                             .w_full()
                             .gap_1p5()
                             .justify_between()
-                            .child(Headline::new("Extensions").size(HeadlineSize::XLarge))
+                            .child(Headline::new("Extensions").size(HeadlineSize::Large))
                             .child(
                                 Button::new("install-dev-extension", "Install Dev Extension")
                                     .style(ButtonStyle::Outlined)

crates/zed_actions/src/lib.rs 🔗

@@ -104,11 +104,11 @@ pub struct Extensions {
     pub id: Option<String>,
 }
 
-/// Opens the external agent registry.
+/// Opens the ACP registry.
 #[derive(PartialEq, Clone, Default, Debug, Deserialize, JsonSchema, Action)]
 #[action(namespace = zed)]
 #[serde(deny_unknown_fields)]
-pub struct AgentRegistry;
+pub struct AcpRegistry;
 
 /// Decreases the font size in the editor buffer.
 #[derive(PartialEq, Clone, Default, Debug, Deserialize, JsonSchema, Action)]