fix(ui): scroll to expanded item (#2088)
Ayman Bagabas
created 1 week ago
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.
Change summary
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(-)
Detailed changes
@@ -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.
@@ -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.
@@ -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