Show prompt usage in agent overflow menu (#29922)

This PR adds prompt usage information, and easy access to managing your
account, to the agent overflow menu:

![CleanShot 2025-05-05 at 10 04
20@2x](https://github.com/user-attachments/assets/337a1a0b-6f71-49a0-9fe7-4fbf2ec1fc27)

Currently this UI will only show after making a request. We'll work on
eagerly getting the usage info later.

Release Notes:

- Added current prompt usage information to the agent menu (`...`) for
Zed AI users
This commit is contained in:
Nate Butler 2025-05-05 10:22:36 -04:00 committed by GitHub
parent 1c44cabaea
commit a72ade8762
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 116 additions and 24 deletions

View file

@ -16,6 +16,8 @@ use super::Tooltip;
pub enum ContextMenuItem {
Separator,
Header(SharedString),
/// title, link_label, link_url
HeaderWithLink(SharedString, SharedString, SharedString), // This could be folded into header
Label(SharedString),
Entry(ContextMenuEntry),
CustomEntry {
@ -332,6 +334,20 @@ impl ContextMenu {
self
}
pub fn header_with_link(
mut self,
title: impl Into<SharedString>,
link_label: impl Into<SharedString>,
link_url: impl Into<SharedString>,
) -> Self {
self.items.push(ContextMenuItem::HeaderWithLink(
title.into(),
link_label.into(),
link_url.into(),
));
self
}
pub fn separator(mut self) -> Self {
self.items.push(ContextMenuItem::Separator);
self
@ -788,6 +804,25 @@ impl ContextMenu {
ContextMenuItem::Header(header) => ListSubHeader::new(header.clone())
.inset(true)
.into_any_element(),
ContextMenuItem::HeaderWithLink(header, label, url) => {
let url = url.clone();
let link_id = ElementId::Name(format!("link-{}", url).into());
ListSubHeader::new(header.clone())
.inset(true)
.end_slot(
Button::new(link_id, label.clone())
.color(Color::Muted)
.label_size(LabelSize::Small)
.size(ButtonSize::None)
.style(ButtonStyle::Transparent)
.on_click(move |_, _, cx| {
let url = url.clone();
cx.open_url(&url);
})
.into_any_element(),
)
.into_any_element()
}
ContextMenuItem::Label(label) => ListItem::new(ix)
.inset(true)
.disabled(true)
@ -1057,6 +1092,7 @@ impl ContextMenuItem {
fn is_selectable(&self) -> bool {
match self {
ContextMenuItem::Header(_)
| ContextMenuItem::HeaderWithLink(_, _, _)
| ContextMenuItem::Separator
| ContextMenuItem::Label { .. } => false,
ContextMenuItem::Entry(ContextMenuEntry { disabled, .. }) => !disabled,

View file

@ -5,6 +5,7 @@ use crate::{Icon, IconName, IconSize, Label, h_flex};
pub struct ListSubHeader {
label: SharedString,
start_slot: Option<IconName>,
end_slot: Option<AnyElement>,
inset: bool,
selected: bool,
}
@ -14,6 +15,7 @@ impl ListSubHeader {
Self {
label: label.into(),
start_slot: None,
end_slot: None,
inset: false,
selected: false,
}
@ -24,6 +26,11 @@ impl ListSubHeader {
self
}
pub fn end_slot(mut self, end_slot: AnyElement) -> Self {
self.end_slot = Some(end_slot);
self
}
pub fn inset(mut self, inset: bool) -> Self {
self.inset = inset;
self
@ -73,7 +80,8 @@ impl RenderOnce for ListSubHeader {
.color(Color::Muted)
.size(LabelSize::Small),
),
),
)
.children(self.end_slot),
)
}
}