From b9838efaaa0bd13dec0adcfff96b9e45b88442d3 Mon Sep 17 00:00:00 2001
From: Danilo Leal <67129314+danilo-leal@users.noreply.github.com>
Date: Fri, 20 Jun 2025 20:28:07 -0300
Subject: [PATCH] agent: Add button to scroll to top of the thread (#33130)
Release Notes:
- agent: Added a button to scroll to top of the thread.
---
assets/icons/arrow_up_alt.svg | 3 +++
crates/agent/src/active_thread.rs | 26 +++++++++++++++++++++-----
crates/icons/src/icons.rs | 1 +
3 files changed, 25 insertions(+), 5 deletions(-)
create mode 100644 assets/icons/arrow_up_alt.svg
diff --git a/assets/icons/arrow_up_alt.svg b/assets/icons/arrow_up_alt.svg
new file mode 100644
index 0000000000..c8cf286a8c
--- /dev/null
+++ b/assets/icons/arrow_up_alt.svg
@@ -0,0 +1,3 @@
+
diff --git a/crates/agent/src/active_thread.rs b/crates/agent/src/active_thread.rs
index b44b301077..05a20e0d56 100644
--- a/crates/agent/src/active_thread.rs
+++ b/crates/agent/src/active_thread.rs
@@ -24,7 +24,7 @@ use editor::{Editor, EditorElement, EditorEvent, EditorStyle, MultiBuffer};
use gpui::{
AbsoluteLength, Animation, AnimationExt, AnyElement, App, ClickEvent, ClipboardEntry,
ClipboardItem, DefiniteLength, EdgesRefinement, Empty, Entity, EventEmitter, Focusable, Hsla,
- ListAlignment, ListState, MouseButton, PlatformDisplay, ScrollHandle, Stateful,
+ ListAlignment, ListOffset, ListState, MouseButton, PlatformDisplay, ScrollHandle, Stateful,
StyleRefinement, Subscription, Task, TextStyle, TextStyleRefinement, Transformation,
UnderlineStyle, WeakEntity, WindowHandle, linear_color_stop, linear_gradient, list, percentage,
pulsating_between,
@@ -48,8 +48,8 @@ use std::time::Duration;
use text::ToPoint;
use theme::ThemeSettings;
use ui::{
- Disclosure, IconButton, KeyBinding, PopoverMenuHandle, Scrollbar, ScrollbarState, TextSize,
- Tooltip, prelude::*,
+ Disclosure, KeyBinding, PopoverMenuHandle, Scrollbar, ScrollbarState, TextSize, Tooltip,
+ prelude::*,
};
use util::ResultExt as _;
use util::markdown::MarkdownCodeBlock;
@@ -1873,6 +1873,14 @@ impl ActiveThread {
}
});
+ let scroll_to_top = IconButton::new(("scroll_to_top", ix), IconName::ArrowUpAlt)
+ .icon_size(IconSize::XSmall)
+ .icon_color(Color::Ignored)
+ .tooltip(Tooltip::text("Scroll To Top"))
+ .on_click(cx.listener(move |this, _, _, cx| {
+ this.scroll_to_top(cx);
+ }));
+
// For all items that should be aligned with the LLM's response.
const RESPONSE_PADDING_X: Pixels = px(19.);
@@ -1982,11 +1990,14 @@ impl ActiveThread {
);
})),
)
- .child(open_as_markdown),
+ .child(open_as_markdown)
+ .child(scroll_to_top),
)
.into_any_element(),
None => feedback_container
- .child(h_flex().child(open_as_markdown))
+ .child(h_flex()
+ .child(open_as_markdown))
+ .child(scroll_to_top)
.into_any_element(),
};
@@ -3476,6 +3487,11 @@ impl ActiveThread {
*is_expanded = !*is_expanded;
}
+ pub fn scroll_to_top(&mut self, cx: &mut Context) {
+ self.list_state.scroll_to(ListOffset::default());
+ cx.notify();
+ }
+
pub fn scroll_to_bottom(&mut self, cx: &mut Context) {
self.list_state.reset(self.messages.len());
cx.notify();
diff --git a/crates/icons/src/icons.rs b/crates/icons/src/icons.rs
index ed599f6641..1826969190 100644
--- a/crates/icons/src/icons.rs
+++ b/crates/icons/src/icons.rs
@@ -28,6 +28,7 @@ pub enum IconName {
ArrowRight,
ArrowRightLeft,
ArrowUp,
+ ArrowUpAlt,
ArrowUpFromLine,
ArrowUpRight,
ArrowUpRightAlt,