on main help sign in
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.

commit0cbaacdbf0d60dab9d3f2cbc94f062663a50ea8a authorAyman Bagabas <ayman.bagabas@gmail.com> dateTue 3 Feb 2026, 15:20 (8 months ago) parentb7e814a
3 files changed+18−9
internal/ui/chat/messages.go+3−1 internal/ui/chat/tools.go+5−6 internal/ui/model/chat.go+10−2
internal/ui/chat/messages.go+3−1
@@ -38,7 +38,9 @@ type Animatable interface {
3838
3939// Expandable is an interface for items that can be expanded or collapsed.
4040type Expandable interface {
41− ToggleExpanded()
41+ // ToggleExpanded toggles the expanded state of the item. It returns
42+ // whether the item is now expanded.
43+ ToggleExpanded() bool
4244}
4345
4446// KeyEventHandler is an interface for items that can handle key events.
internal/ui/chat/tools.go+5−6
@@ -157,6 +157,8 @@ type baseToolMessageItem struct {
157157 expandedContent bool
158158}
159159
160+var _ Expandable = (*baseToolMessageItem)(nil)
161+
160162// newBaseToolMessageItem is the internal constructor for base tool message items.
161163func newBaseToolMessageItem(
162164 sty *styles.Styles,
@@ -398,18 +400,15 @@ func (t *baseToolMessageItem) SetSpinningFunc(fn SpinningFunc) {
398400}
399401
400402// ToggleExpanded toggles the expanded state of the thinking box.
401−func (t *baseToolMessageItem) ToggleExpanded() {
403+func (t *baseToolMessageItem) ToggleExpanded() bool {
402404 t.expandedContent = !t.expandedContent
403405 t.clearCache()
406+ return t.expandedContent
404407}
405408
406409// HandleMouseClick implements MouseClickable.
407410func (t *baseToolMessageItem) HandleMouseClick(btn ansi.MouseButton, x, y int) bool {
408− if btn != ansi.MouseLeft {
409− return false
410− }
411− t.ToggleExpanded()
412− return true
411+ return btn == ansi.MouseLeft
413412}
414413
415414// HandleKeyEvent implements KeyEventHandler.
internal/ui/model/chat.go+10−2
@@ -438,6 +438,7 @@ func (m *Chat) MessageItem(id string) chat.MessageItem {
438438func (m *Chat) ToggleExpandedSelectedItem() {
439439 if expandable, ok := m.list.SelectedItem().(chat.Expandable); ok {
440440 expandable.ToggleExpanded()
441+ m.list.ScrollToIndex(m.list.Selected())
441442 }
442443}
443444
@@ -538,8 +539,15 @@ func (m *Chat) HandleDelayedClick(msg DelayedClickMsg) bool {
538539 }
539540
540541 // Execute the click action (e.g., expansion).
541− if clickable, ok := m.list.SelectedItem().(list.MouseClickable); ok {
542− return clickable.HandleMouseClick(ansi.MouseButton1, msg.X, msg.Y)
542+ selectedItem := m.list.SelectedItem()
543+ if clickable, ok := selectedItem.(list.MouseClickable); ok {
544+ handled := clickable.HandleMouseClick(ansi.MouseButton1, msg.X, msg.Y)
545+ // Toggle expansion if applicable.
546+ if expandable, ok := selectedItem.(chat.Expandable); ok {
547+ expandable.ToggleExpanded()
548+ }
549+ m.list.ScrollToIndex(m.list.Selected())
550+ return handled
543551 }
544552
545553 return false