ui: Fix end_hover gradient overlay in `ListItem` (#51237)

Danilo Leal created

This PR adds a bool method to the `ListItem` that allows to turn on the
gradient overlay in the `end_hover_slot`. Places that are not the
sidebar, at least at the moment, don't need it. And with the previous
code, they were getting it, which felt wrong.

Release Notes:

- N/A

Change summary

crates/sidebar/src/sidebar.rs              | 20 ++++----------------
crates/ui/src/components/list/list_item.rs | 13 ++++++++++++-
2 files changed, 16 insertions(+), 17 deletions(-)

Detailed changes

crates/sidebar/src/sidebar.rs 🔗

@@ -19,9 +19,8 @@ use std::mem;
 use theme::{ActiveTheme, ThemeSettings};
 use ui::utils::TRAFFIC_LIGHT_PADDING;
 use ui::{
-    AgentThreadStatus, ButtonStyle, GradientFade, HighlightedLabel, IconButtonShape, KeyBinding,
-    ListItem, PopoverMenu, PopoverMenuHandle, Tab, ThreadItem, TintColor, Tooltip, WithScrollbar,
-    prelude::*,
+    AgentThreadStatus, ButtonStyle, HighlightedLabel, IconButtonShape, KeyBinding, ListItem,
+    PopoverMenu, PopoverMenuHandle, Tab, ThreadItem, TintColor, Tooltip, WithScrollbar, prelude::*,
 };
 use util::path_list::PathList;
 use workspace::{
@@ -795,17 +794,6 @@ impl Sidebar {
                 .into_any_element()
         };
 
-        let color = cx.theme().colors();
-        let base_bg = if is_active_workspace {
-            color.ghost_element_selected
-        } else {
-            color.panel_background
-        };
-        let gradient_overlay =
-            GradientFade::new(base_bg, color.element_hover, color.element_active)
-                .width(px(48.0))
-                .group_name(group_name.clone());
-
         ListItem::new(id)
             .group_name(group_name)
             .toggle_state(is_active_workspace)
@@ -822,9 +810,9 @@ impl Sidebar {
                             .size(IconSize::Small)
                             .color(Color::Custom(cx.theme().colors().icon_muted.opacity(0.6))),
                     )
-                    .child(label)
-                    .child(gradient_overlay),
+                    .child(label),
             )
+            .end_hover_gradient_overlay(true)
             .end_hover_slot(
                 h_flex()
                     .when(workspace_count > 1, |this| {

crates/ui/src/components/list/list_item.rs 🔗

@@ -31,6 +31,9 @@ pub struct ListItem {
     /// A slot for content that appears on hover after the children
     /// It will obscure the `end_slot` when visible.
     end_hover_slot: Option<AnyElement>,
+    /// When true, renders a gradient fade overlay before the `end_hover_slot`
+    /// to smoothly truncate overflowing content.
+    end_hover_gradient_overlay: bool,
     toggle: Option<bool>,
     inset: bool,
     on_click: Option<Box<dyn Fn(&ClickEvent, &mut Window, &mut App) + 'static>>,
@@ -60,6 +63,7 @@ impl ListItem {
             start_slot: None,
             end_slot: None,
             end_hover_slot: None,
+            end_hover_gradient_overlay: false,
             toggle: None,
             inset: false,
             on_click: None,
@@ -166,6 +170,11 @@ impl ListItem {
         self
     }
 
+    pub fn end_hover_gradient_overlay(mut self, show: bool) -> Self {
+        self.end_hover_gradient_overlay = show;
+        self
+    }
+
     pub fn outlined(mut self) -> Self {
         self.outlined = true;
         self
@@ -362,7 +371,9 @@ impl RenderOnce for ListItem {
                                 .right(DynamicSpacing::Base06.rems(cx))
                                 .top_0()
                                 .visible_on_hover("list_item")
-                                .child(end_hover_gradient_overlay)
+                                .when(self.end_hover_gradient_overlay, |this| {
+                                    this.child(end_hover_gradient_overlay)
+                                })
                                 .child(end_hover_slot),
                         )
                     }),