workflow: Add button to open the step view (#16387)

Danilo Leal created

This PR adds an icon button that appears as you hover over the step header, which allows users to visit the step view.

---

Release Notes:

- N/A

Change summary

assets/icons/search_code.svg               |  1 
crates/assistant/src/assistant_panel.rs    | 52 +++++++++++++++--------
crates/assistant/src/workflow/step_view.rs |  2 
crates/ui/src/components/icon.rs           |  2 
4 files changed, 38 insertions(+), 19 deletions(-)

Detailed changes

assets/icons/search_code.svg 🔗

@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-search-code"><path d="m13 13.5 2-2.5-2-2.5"/><path d="m21 21-4.3-4.3"/><path d="M9 8.5 7 11l2 2.5"/><circle cx="11" cy="11" r="8"/></svg>

crates/assistant/src/assistant_panel.rs 🔗

@@ -36,10 +36,10 @@ use fs::Fs;
 use gpui::{
     canvas, div, img, percentage, point, pulsating_between, size, Action, Animation, AnimationExt,
     AnyElement, AnyView, AppContext, AsyncWindowContext, ClipboardEntry, ClipboardItem,
-    Context as _, CursorStyle, DismissEvent, Empty, Entity, EntityId, EventEmitter, FocusHandle,
-    FocusableView, FontWeight, InteractiveElement, IntoElement, Model, ParentElement, Pixels,
-    ReadGlobal, Render, RenderImage, SharedString, Size, StatefulInteractiveElement, Styled,
-    Subscription, Task, Transformation, UpdateGlobal, View, VisualContext, WeakView, WindowContext,
+    Context as _, DismissEvent, Empty, Entity, EntityId, EventEmitter, FocusHandle, FocusableView,
+    FontWeight, InteractiveElement, IntoElement, Model, ParentElement, Pixels, ReadGlobal, Render,
+    RenderImage, SharedString, Size, StatefulInteractiveElement, Styled, Subscription, Task,
+    Transformation, UpdateGlobal, View, VisualContext, WeakView, WindowContext,
 };
 use indexed_docs::IndexedDocsStore;
 use language::{
@@ -69,8 +69,8 @@ use ui::TintColor;
 use ui::{
     prelude::*,
     utils::{format_distance_from_now, DateTimeType},
-    Avatar, AvatarShape, ButtonLike, ContextMenu, Disclosure, ElevationIndex, KeyBinding, ListItem,
-    ListItemSpacing, PopoverMenu, PopoverMenuHandle, Tooltip,
+    Avatar, AvatarShape, ButtonLike, ContextMenu, Disclosure, ElevationIndex, IconButtonShape,
+    KeyBinding, ListItem, ListItemSpacing, PopoverMenu, PopoverMenuHandle, Tooltip,
 };
 use util::ResultExt;
 use workspace::{
@@ -2539,19 +2539,35 @@ impl ContextEditor {
                                         div().child(step_label)
                                     };
 
-                                    let step_label = step_label
+                                    let step_label_element = step_label.into_any_element();
+
+                                    let step_label = h_flex()
                                         .id("step")
-                                        .cursor(CursorStyle::PointingHand)
-                                        .on_click({
-                                            let this = weak_self.clone();
-                                            let step_range = step_range.clone();
-                                            move |_, cx| {
-                                                this.update(cx, |this, cx| {
-                                                    this.open_workflow_step(step_range.clone(), cx);
-                                                })
-                                                .ok();
-                                            }
-                                        });
+                                        .group("step-label")
+                                        .items_center()
+                                        .gap_1()
+                                        .child(step_label_element)
+                                        .child(
+                                            IconButton::new("edit-step", IconName::SearchCode)
+                                                .size(ButtonSize::Compact)
+                                                .icon_size(IconSize::Small)
+                                                .shape(IconButtonShape::Square)
+                                                .visible_on_hover("step-label")
+                                                .tooltip(|cx| Tooltip::text("Open Step View", cx))
+                                                .on_click({
+                                                    let this = weak_self.clone();
+                                                    let step_range = step_range.clone();
+                                                    move |_, cx| {
+                                                        this.update(cx, |this, cx| {
+                                                            this.open_workflow_step(
+                                                                step_range.clone(),
+                                                                cx,
+                                                            );
+                                                        })
+                                                        .ok();
+                                                    }
+                                                }),
+                                        );
 
                                     div()
                                         .w_full()

crates/assistant/src/workflow/step_view.rs 🔗

@@ -273,7 +273,7 @@ impl Item for WorkflowStepView {
     }
 
     fn tab_icon(&self, _cx: &WindowContext) -> Option<ui::Icon> {
-        Some(Icon::new(IconName::Pencil))
+        Some(Icon::new(IconName::SearchCode))
     }
 
     fn to_item_events(event: &Self::Event, mut f: impl FnMut(item::ItemEvent)) {

crates/ui/src/components/icon.rs 🔗

@@ -230,6 +230,7 @@ pub enum IconName {
     Save,
     Screen,
     SearchSelection,
+    SearchCode,
     SelectAll,
     Server,
     Settings,
@@ -396,6 +397,7 @@ impl IconName {
             IconName::Save => "icons/save.svg",
             IconName::Screen => "icons/desktop.svg",
             IconName::SearchSelection => "icons/search_selection.svg",
+            IconName::SearchCode => "icons/search_code.svg",
             IconName::SelectAll => "icons/select_all.svg",
             IconName::Server => "icons/server.svg",
             IconName::Settings => "icons/file_icons/settings.svg",