@@ -790,15 +790,28 @@ func (l *list[T]) blurSelectedItem() tea.Cmd {
790790 return tea.Batch(cmds...)
791791}
792792
793−// render iterator renders items starting from the specific index and limits hight if limitHeight != -1
793+// renderFragment holds updated rendered view fragments
794+type renderFragment struct {
795+ view string
796+ gap int
797+}
798+
799+// renderIterator renders items starting from the specific index and limits height if limitHeight != -1
794800// returns the last index and the rendered content so far
795801// we pass the rendered content around and don't use l.rendered to prevent jumping of the content
796802func (l *list[T]) renderIterator(startInx int, limitHeight bool, rendered string) (string, int) {
803+ var fragments []renderFragment
804+
797805 currentContentHeight := lipgloss.Height(rendered) - 1
798806 itemsLen := l.items.Len()
807+ finalIndex := itemsLen
808+
809+ // first pass: accumulate all fragments to render until the height limit is
810+ // reached
799811 for i := startInx; i < itemsLen; i++ {
800− if currentContentHeight >= l.height && limitHeight {
801− return rendered, i
812+ if limitHeight && currentContentHeight >= l.height {
813+ finalIndex = i
814+ break
802815 }
803816 // cool way to go through the list in both directions
804817 inx := i
@@ -811,6 +824,7 @@ func (l *list[T]) renderIterator(startInx int, limitHeight bool, rendered string
811824 if !ok {
812825 continue
813826 }
827+
814828 var rItem renderedItem
815829 if cache, ok := l.renderedItems.Get(item.ID()); ok {
816830 rItem = cache
@@ -820,19 +834,42 @@ func (l *list[T]) renderIterator(startInx int, limitHeight bool, rendered string
820834 rItem.end = currentContentHeight + rItem.height - 1
821835 l.renderedItems.Set(item.ID(), rItem)
822836 }
837+
823838 gap := l.gap + 1
824839 if inx == itemsLen-1 {
825840 gap = 0
826841 }
827842
828− if l.direction == DirectionForward {
829− rendered += rItem.view + strings.Repeat("\n", gap)
830− } else {
831− rendered = rItem.view + strings.Repeat("\n", gap) + rendered
832− }
843+ fragments = append(fragments, renderFragment{view: rItem.view, gap: gap})
844+
833845 currentContentHeight = rItem.end + 1 + l.gap
834846 }
835− return rendered, itemsLen
847+
848+ // second pass: build rendered string efficiently
849+ var b strings.Builder
850+ if l.direction == DirectionForward {
851+ b.WriteString(rendered)
852+ for _, f := range fragments {
853+ b.WriteString(f.view)
854+ for range f.gap {
855+ b.WriteByte('\n')
856+ }
857+ }
858+
859+ return b.String(), finalIndex
860+ }
861+
862+ // iterate backwards as fragments are in reversed order
863+ for i := len(fragments) - 1; i >= 0; i-- {
864+ f := fragments[i]
865+ b.WriteString(f.view)
866+ for range f.gap {
867+ b.WriteByte('\n')
868+ }
869+ }
870+ b.WriteString(rendered)
871+
872+ return b.String(), finalIndex
836873}
837874
838875func (l *list[T]) renderItem(item Item) renderedItem {