From 02b1e3a3c132ae2e186d5ac48bb93f8e3e9b2ca2 Mon Sep 17 00:00:00 2001 From: Danilo Leal <67129314+danilo-leal@users.noreply.github.com> Date: Tue, 5 Nov 2024 09:07:26 -0300 Subject: [PATCH] assistant: Adjust the toolbar design (#20101) This PR's most relevant change is removing the three-dot menu dropdown from the assistant toolbar. The "Regenerate Title" button is now only visible on hover and it appears on the far right of the title input. Screenshot 2024-11-04 at 13 31 37 Release Notes: - N/A --- assets/icons/refresh_title.svg | 5 + crates/assistant/src/assistant_panel.rs | 204 +++++++++--------------- crates/ui/src/components/icon.rs | 1 + 3 files changed, 77 insertions(+), 133 deletions(-) create mode 100644 assets/icons/refresh_title.svg diff --git a/assets/icons/refresh_title.svg b/assets/icons/refresh_title.svg new file mode 100644 index 0000000000..bd3657d48c --- /dev/null +++ b/assets/icons/refresh_title.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/crates/assistant/src/assistant_panel.rs b/crates/assistant/src/assistant_panel.rs index 9a16b032ce..e1b3a3d978 100644 --- a/crates/assistant/src/assistant_panel.rs +++ b/crates/assistant/src/assistant_panel.rs @@ -441,48 +441,49 @@ impl AssistantPanel { .map_or(false, |item| item.downcast::().is_some()), ); let _pane = cx.view().clone(); - let right_children = h_flex() - .gap(Spacing::Small.rems(cx)) - .child( - IconButton::new("new-context", IconName::Plus) - .on_click( - cx.listener(|_, _, cx| { + let right_children = + h_flex() + .gap(Spacing::XSmall.rems(cx)) + .child( + IconButton::new("new-context", IconName::Plus) + .on_click(cx.listener(|_, _, cx| { cx.dispatch_action(NewContext.boxed_clone()) - }), - ) - .tooltip(move |cx| { - Tooltip::for_action_in( - "New Context", - &NewContext, - &focus_handle, - cx, - ) - }), - ) - .child( - PopoverMenu::new("assistant-panel-popover-menu") - .trigger( - IconButton::new("menu", IconName::Menu).icon_size(IconSize::Small), - ) - .menu(move |cx| { - let zoom_label = if _pane.read(cx).is_zoomed() { - "Zoom Out" - } else { - "Zoom In" - }; - let focus_handle = _pane.focus_handle(cx); - Some(ContextMenu::build(cx, move |menu, _| { - menu.context(focus_handle.clone()) - .action("New Context", Box::new(NewContext)) - .action("History", Box::new(DeployHistory)) - .action("Prompt Library", Box::new(DeployPromptLibrary)) - .action("Configure", Box::new(ShowConfiguration)) - .action(zoom_label, Box::new(ToggleZoom)) })) - }), - ) - .into_any_element() - .into(); + .tooltip(move |cx| { + Tooltip::for_action_in( + "New Context", + &NewContext, + &focus_handle, + cx, + ) + }), + ) + .child( + PopoverMenu::new("assistant-panel-popover-menu") + .trigger( + IconButton::new("menu", IconName::EllipsisVertical) + .icon_size(IconSize::Small) + .tooltip(|cx| Tooltip::text("Toggle Assistant Menu", cx)), + ) + .menu(move |cx| { + let zoom_label = if _pane.read(cx).is_zoomed() { + "Zoom Out" + } else { + "Zoom In" + }; + let focus_handle = _pane.focus_handle(cx); + Some(ContextMenu::build(cx, move |menu, _| { + menu.context(focus_handle.clone()) + .action("New Context", Box::new(NewContext)) + .action("History", Box::new(DeployHistory)) + .action("Prompt Library", Box::new(DeployPromptLibrary)) + .action("Configure", Box::new(ShowConfiguration)) + .action(zoom_label, Box::new(ToggleZoom)) + })) + }), + ) + .into_any_element() + .into(); (Some(left_children.into_any_element()), right_children) }); @@ -4367,26 +4368,11 @@ impl FollowableItem for ContextEditor { pub struct ContextEditorToolbarItem { fs: Arc, - workspace: WeakView, active_context_editor: Option>, model_summary_editor: View, model_selector_menu_handle: PopoverMenuHandle>, } -fn active_editor_focus_handle( - workspace: &WeakView, - cx: &WindowContext<'_>, -) -> Option { - workspace.upgrade().and_then(|workspace| { - Some( - workspace - .read(cx) - .active_item_as::(cx)? - .focus_handle(cx), - ) - }) -} - fn render_inject_context_menu( active_context_editor: WeakView, cx: &mut WindowContext<'_>, @@ -4413,7 +4399,6 @@ impl ContextEditorToolbarItem { ) -> Self { Self { fs: workspace.app_state().fs.clone(), - workspace: workspace.weak_handle(), active_context_editor: None, model_summary_editor, model_selector_menu_handle, @@ -4466,16 +4451,30 @@ impl ContextEditorToolbarItem { impl Render for ContextEditorToolbarItem { fn render(&mut self, cx: &mut ViewContext) -> impl IntoElement { let left_side = h_flex() - .pl_1() - .gap_2() - .flex_1() - .min_w(rems(DEFAULT_TAB_TITLE.len() as f32)) - .when(self.active_context_editor.is_some(), |left_side| { - left_side.child(self.model_summary_editor.clone()) - }); + .group("chat-title-group") + .pl_0p5() + .gap_1() + .items_center() + .flex_grow() + .child( + div() + .w_full() + .when(self.active_context_editor.is_some(), |left_side| { + left_side.child(self.model_summary_editor.clone()) + }), + ) + .child( + div().visible_on_hover("chat-title-group").child( + IconButton::new("regenerate-context", IconName::RefreshTitle) + .shape(ui::IconButtonShape::Square) + .tooltip(|cx| Tooltip::text("Regenerate Title", cx)) + .on_click(cx.listener(move |_, _, cx| { + cx.emit(ContextEditorToolbarItemEvent::RegenerateSummary) + })), + ), + ); let active_provider = LanguageModelRegistry::read_global(cx).active_provider(); let active_model = LanguageModelRegistry::read_global(cx).active_model(); - let weak_self = cx.view().downgrade(); let right_side = h_flex() .gap_2() // TODO display this in a nicer way, once we have a design for it. @@ -4488,7 +4487,6 @@ impl Render for ContextEditorToolbarItem { // let scan_items_remaining = cx.update_global(|db: &mut SemanticDb, cx| { // project.and_then(|project| db.remaining_summaries(&project, cx)) // }); - // scan_items_remaining // .map(|remaining_items| format!("Files to scan: {}", remaining_items)) // }) @@ -4510,9 +4508,13 @@ impl Render for ContextEditorToolbarItem { (Some(provider), Some(model)) => h_flex() .gap_1() .child( - Icon::new(model.icon().unwrap_or_else(|| provider.icon())) - .color(Color::Muted) - .size(IconSize::XSmall), + Icon::new( + model + .icon() + .unwrap_or_else(|| provider.icon()), + ) + .color(Color::Muted) + .size(IconSize::XSmall), ) .child( Label::new(model.name().0) @@ -4538,71 +4540,7 @@ impl Render for ContextEditorToolbarItem { ) .with_handle(self.model_selector_menu_handle.clone()), ) - .children(self.render_remaining_tokens(cx)) - .child( - PopoverMenu::new("context-editor-popover") - .trigger( - IconButton::new("context-editor-trigger", IconName::EllipsisVertical) - .icon_size(IconSize::Small) - .tooltip(|cx| Tooltip::text("Open Context Options", cx)), - ) - .menu({ - let weak_self = weak_self.clone(); - move |cx| { - let weak_self = weak_self.clone(); - Some(ContextMenu::build(cx, move |menu, cx| { - let context = weak_self - .update(cx, |this, cx| { - active_editor_focus_handle(&this.workspace, cx) - }) - .ok() - .flatten(); - menu.when_some(context, |menu, context| menu.context(context)) - .entry("Regenerate Context Title", None, { - let weak_self = weak_self.clone(); - move |cx| { - weak_self - .update(cx, |_, cx| { - cx.emit(ContextEditorToolbarItemEvent::RegenerateSummary) - }) - .ok(); - } - }) - .custom_entry( - |_| { - h_flex() - .w_full() - .justify_between() - .gap_2() - .child(Label::new("Add Context")) - .child(Label::new("/ command").color(Color::Muted)) - .into_any() - }, - { - let weak_self = weak_self.clone(); - move |cx| { - weak_self - .update(cx, |this, cx| { - if let Some(editor) = - &this.active_context_editor - { - editor - .update(cx, |this, cx| { - this.slash_menu_handle - .toggle(cx); - }) - .ok(); - } - }) - .ok(); - } - }, - ) - .action("Add Selection", QuoteSelection.boxed_clone()) - })) - } - }), - ); + .children(self.render_remaining_tokens(cx)); h_flex() .size_full() diff --git a/crates/ui/src/components/icon.rs b/crates/ui/src/components/icon.rs index e11b6edf32..3aa3dc7615 100644 --- a/crates/ui/src/components/icon.rs +++ b/crates/ui/src/components/icon.rs @@ -234,6 +234,7 @@ pub enum IconName { Public, PullRequest, Quote, + RefreshTitle, Regex, ReplNeutral, Replace,