Adjust design of the slash command picker (#19973)

This PR removes the quote selection icon button from the footer and adds
it in the picker, and adds an icon field to each command entry. Final
result looks like:


https://github.com/user-attachments/assets/d177f1c1-b6f6-4652-9434-f6291b279e34

Release Notes:

- N/A
This commit is contained in:
Danilo Leal 2024-10-30 19:42:42 -03:00 committed by GitHub
parent f80eb264fb
commit 6d5784daa6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
15 changed files with 185 additions and 110 deletions

View file

@ -1,19 +1,13 @@
use std::sync::Arc;
use assistant_slash_command::SlashCommandRegistry;
use gpui::AnyElement;
use gpui::DismissEvent;
use gpui::WeakView;
use picker::PickerEditorPosition;
use ui::ListItemSpacing;
use gpui::SharedString;
use gpui::Task;
use picker::{Picker, PickerDelegate};
use ui::{prelude::*, ListItem, PopoverMenu, PopoverTrigger};
use gpui::{AnyElement, DismissEvent, SharedString, Task, WeakView};
use picker::{Picker, PickerDelegate, PickerEditorPosition};
use ui::{prelude::*, KeyBinding, ListItem, ListItemSpacing, PopoverMenu, PopoverTrigger};
use crate::assistant_panel::ContextEditor;
use crate::QuoteSelection;
#[derive(IntoElement)]
pub(super) struct SlashCommandSelector<T: PopoverTrigger> {
@ -27,6 +21,7 @@ struct SlashCommandInfo {
name: SharedString,
description: SharedString,
args: Option<SharedString>,
icon: IconName,
}
#[derive(Clone)]
@ -37,6 +32,7 @@ enum SlashCommandEntry {
renderer: fn(&mut WindowContext<'_>) -> AnyElement,
on_confirm: fn(&mut WindowContext<'_>),
},
QuoteButton,
}
impl AsRef<str> for SlashCommandEntry {
@ -44,6 +40,7 @@ impl AsRef<str> for SlashCommandEntry {
match self {
SlashCommandEntry::Info(SlashCommandInfo { name, .. })
| SlashCommandEntry::Advert { name, .. } => name,
SlashCommandEntry::QuoteButton => "Quote Selection",
}
}
}
@ -145,16 +142,23 @@ impl PickerDelegate for SlashCommandDelegate {
}
ret
}
fn confirm(&mut self, _secondary: bool, cx: &mut ViewContext<Picker<Self>>) {
if let Some(command) = self.filtered_commands.get(self.selected_index) {
if let SlashCommandEntry::Info(info) = command {
self.active_context_editor
.update(cx, |context_editor, cx| {
context_editor.insert_command(&info.name, cx)
})
.ok();
} else if let SlashCommandEntry::Advert { on_confirm, .. } = command {
on_confirm(cx);
match command {
SlashCommandEntry::Info(info) => {
self.active_context_editor
.update(cx, |context_editor, cx| {
context_editor.insert_command(&info.name, cx)
})
.ok();
}
SlashCommandEntry::QuoteButton => {
cx.dispatch_action(Box::new(QuoteSelection));
}
SlashCommandEntry::Advert { on_confirm, .. } => {
on_confirm(cx);
}
}
cx.emit(DismissEvent);
}
@ -181,46 +185,78 @@ impl PickerDelegate for SlashCommandDelegate {
.spacing(ListItemSpacing::Dense)
.selected(selected)
.child(
h_flex()
v_flex()
.group(format!("command-entry-label-{ix}"))
.w_full()
.min_w(px(250.))
.child(
v_flex()
.child(
h_flex()
.child(div().font_buffer(cx).child({
let mut label = format!("/{}", info.name);
if let Some(args) =
info.args.as_ref().filter(|_| selected)
{
label.push_str(&args);
}
Label::new(label).size(LabelSize::Small)
}))
.children(info.args.clone().filter(|_| !selected).map(
|args| {
div()
.font_buffer(cx)
.child(
Label::new(args)
.size(LabelSize::Small)
.color(Color::Muted),
)
.visible_on_hover(format!(
"command-entry-label-{ix}"
))
},
)),
)
.child(
Label::new(info.description.clone())
.size(LabelSize::Small)
.color(Color::Muted),
),
h_flex()
.gap_1p5()
.child(Icon::new(info.icon).size(IconSize::XSmall))
.child(div().font_buffer(cx).child({
let mut label = format!("{}", info.name);
if let Some(args) = info.args.as_ref().filter(|_| selected)
{
label.push_str(&args);
}
Label::new(label).size(LabelSize::Small)
}))
.children(info.args.clone().filter(|_| !selected).map(
|args| {
div()
.font_buffer(cx)
.child(
Label::new(args)
.size(LabelSize::Small)
.color(Color::Muted),
)
.visible_on_hover(format!(
"command-entry-label-{ix}"
))
},
)),
)
.child(
Label::new(info.description.clone())
.size(LabelSize::Small)
.color(Color::Muted),
),
),
),
SlashCommandEntry::QuoteButton => {
let focus = cx.focus_handle();
let key_binding = KeyBinding::for_action_in(&QuoteSelection, &focus, cx);
Some(
ListItem::new(ix)
.inset(true)
.spacing(ListItemSpacing::Dense)
.selected(selected)
.child(
v_flex()
.child(
h_flex()
.gap_1p5()
.child(Icon::new(IconName::Quote).size(IconSize::XSmall))
.child(
div().font_buffer(cx).child(
Label::new("selection").size(LabelSize::Small),
),
),
)
.child(
h_flex()
.gap_1p5()
.child(
Label::new("Insert editor selection")
.color(Color::Muted)
.size(LabelSize::Small),
)
.children(key_binding.map(|kb| kb.render(cx))),
),
),
)
}
SlashCommandEntry::Advert { renderer, .. } => Some(
ListItem::new(ix)
.inset(true)
@ -251,31 +287,50 @@ impl<T: PopoverTrigger> RenderOnce for SlashCommandSelector<T> {
name: command_name.into(),
description: menu_text,
args,
icon: command.icon(),
}))
})
.chain([SlashCommandEntry::Advert {
name: "create-your-command".into(),
renderer: |cx| {
v_flex()
.child(
h_flex()
.font_buffer(cx)
.items_center()
.gap_1()
.child(div().font_buffer(cx).child(
Label::new("create-your-command").size(LabelSize::Small),
))
.child(Icon::new(IconName::ArrowUpRight).size(IconSize::XSmall)),
)
.child(
Label::new("Learn how to create a custom command")
.size(LabelSize::Small)
.color(Color::Muted),
)
.into_any_element()
.chain([
SlashCommandEntry::Advert {
name: "create-your-command".into(),
renderer: |cx| {
v_flex()
.w_full()
.child(
h_flex()
.w_full()
.font_buffer(cx)
.items_center()
.justify_between()
.child(
h_flex()
.items_center()
.gap_1p5()
.child(Icon::new(IconName::Plus).size(IconSize::XSmall))
.child(
div().font_buffer(cx).child(
Label::new("create-your-command")
.size(LabelSize::Small),
),
),
)
.child(
Icon::new(IconName::ArrowUpRight)
.size(IconSize::XSmall)
.color(Color::Muted),
),
)
.child(
Label::new("Create your custom command")
.size(LabelSize::Small)
.color(Color::Muted),
)
.into_any_element()
},
on_confirm: |cx| cx.open_url("https://zed.dev/docs/extensions/slash-commands"),
},
on_confirm: |cx| cx.open_url("https://zed.dev/docs/extensions/slash-commands"),
}])
SlashCommandEntry::QuoteButton,
])
.collect::<Vec<_>>();
let delegate = SlashCommandDelegate {