From 0cbaacdbf0d60dab9d3f2cbc94f062663a50ea8a Mon Sep 17 00:00:00 2001 From: Ayman Bagabas Date: Tue, 3 Feb 2026 15:20:17 +0300 Subject: [PATCH] fix(ui): scroll to expanded item (#2088) Scroll the chat view to ensure that an expanded message item is fully visible after toggling its expanded state. This improves user experience by keeping the context of the expanded content in view. --- internal/ui/chat/messages.go | 4 +++- internal/ui/chat/tools.go | 11 +++++------ internal/ui/model/chat.go | 12 ++++++++++-- 3 files changed, 18 insertions(+), 9 deletions(-) diff --git a/internal/ui/chat/messages.go b/internal/ui/chat/messages.go index b9f16adf3ad7d5b7097e639892b1c6a6f1c22042..0c5668a20d52c5975dc63cb37da8090e9aa0ca7f 100644 --- a/internal/ui/chat/messages.go +++ b/internal/ui/chat/messages.go @@ -38,7 +38,9 @@ type Animatable interface { // Expandable is an interface for items that can be expanded or collapsed. type Expandable interface { - ToggleExpanded() + // ToggleExpanded toggles the expanded state of the item. It returns + // whether the item is now expanded. + ToggleExpanded() bool } // KeyEventHandler is an interface for items that can handle key events. diff --git a/internal/ui/chat/tools.go b/internal/ui/chat/tools.go index 07c3d98e6f60d319df8eff3699a057ad562771b7..c53b36a86ad98c4f7e3ca30608cf2fd43e87cf26 100644 --- a/internal/ui/chat/tools.go +++ b/internal/ui/chat/tools.go @@ -157,6 +157,8 @@ type baseToolMessageItem struct { expandedContent bool } +var _ Expandable = (*baseToolMessageItem)(nil) + // newBaseToolMessageItem is the internal constructor for base tool message items. func newBaseToolMessageItem( sty *styles.Styles, @@ -398,18 +400,15 @@ func (t *baseToolMessageItem) SetSpinningFunc(fn SpinningFunc) { } // ToggleExpanded toggles the expanded state of the thinking box. -func (t *baseToolMessageItem) ToggleExpanded() { +func (t *baseToolMessageItem) ToggleExpanded() bool { t.expandedContent = !t.expandedContent t.clearCache() + return t.expandedContent } // HandleMouseClick implements MouseClickable. func (t *baseToolMessageItem) HandleMouseClick(btn ansi.MouseButton, x, y int) bool { - if btn != ansi.MouseLeft { - return false - } - t.ToggleExpanded() - return true + return btn == ansi.MouseLeft } // HandleKeyEvent implements KeyEventHandler. diff --git a/internal/ui/model/chat.go b/internal/ui/model/chat.go index 4abe68f27aa367b5ff81ebefc89633310f93e81d..723e97fb76c04d75922a5aec60d9afa970e41d97 100644 --- a/internal/ui/model/chat.go +++ b/internal/ui/model/chat.go @@ -438,6 +438,7 @@ func (m *Chat) MessageItem(id string) chat.MessageItem { func (m *Chat) ToggleExpandedSelectedItem() { if expandable, ok := m.list.SelectedItem().(chat.Expandable); ok { expandable.ToggleExpanded() + m.list.ScrollToIndex(m.list.Selected()) } } @@ -538,8 +539,15 @@ func (m *Chat) HandleDelayedClick(msg DelayedClickMsg) bool { } // Execute the click action (e.g., expansion). - if clickable, ok := m.list.SelectedItem().(list.MouseClickable); ok { - return clickable.HandleMouseClick(ansi.MouseButton1, msg.X, msg.Y) + selectedItem := m.list.SelectedItem() + if clickable, ok := selectedItem.(list.MouseClickable); ok { + handled := clickable.HandleMouseClick(ansi.MouseButton1, msg.X, msg.Y) + // Toggle expansion if applicable. + if expandable, ok := selectedItem.(chat.Expandable); ok { + expandable.ToggleExpanded() + } + m.list.ScrollToIndex(m.list.Selected()) + return handled } return false