on main help sign in
chore: more tests
commit3e18da56ec60fa96c497aee5c49d962a534ccc77 authorKujtim Hoxha <kujtimii.h@gmail.com> dateMon 21 Jul 2025, 09:56 (1 year ago) parent99bbcce
9 files changed+239−58
internal/tui/exp/list/list.go+70−12 internal/tui/exp/list/list_test.go+159−38 internal/tui/exp/list/testdata/TestBackwardList/should_move_at_max_to_the_top.golden+1−1 internal/tui/exp/list/testdata/TestBackwardList/should_move_up.golden+1−1 internal/tui/exp/list/testdata/TestBackwardList/within_height.golden−2 internal/tui/exp/list/testdata/TestForwardList/should_move_at_max_to_the_top.golden → internal/tui/exp/list/testdata/TestForwardList/should_move_at_max_to_the_bottom.golden+1−1 internal/tui/exp/list/testdata/TestForwardList/should_move_down.golden+1−1 internal/tui/exp/list/testdata/TestForwardList/within_height.golden−2 internal/tui/exp/list/testdata/TestListSelection/should_skip_none_selectable_items_initially.golden+6
internal/tui/exp/list/list.go+70−12
@@ -1,6 +1,7 @@
11package list
22
33import (
4+ "fmt"
45 "strings"
56
67 tea "github.com/charmbracelet/bubbletea/v2"
@@ -132,19 +133,20 @@ func (l *list) View() string {
132133 view := l.rendered
133134 lines := strings.Split(view, "\n")
134135
135− start, end := l.viewPosition(len(lines))
136− lines = lines[start:end]
136+ start, end := l.viewPosition()
137+ lines = lines[start : end+1]
137138 return strings.Join(lines, "\n")
138139}
139140
140−func (l *list) viewPosition(total int) (int, int) {
141+func (l *list) viewPosition() (int, int) {
141142 start, end := 0, 0
143+ renderedLines := lipgloss.Height(l.rendered) - 1
142144 if l.direction == Forward {
143145 start = max(0, l.offset)
144− end = min(l.offset+l.listHeight(), total)
146+ end = min(l.offset+l.listHeight()-1, renderedLines)
145147 } else {
146− start = max(0, total-l.offset-l.listHeight())
147− end = max(0, total-l.offset)
148+ start = max(0, renderedLines-l.offset-l.listHeight()+1)
149+ end = max(0, renderedLines-l.offset)
148150 }
149151 return start, end
150152}
@@ -200,20 +202,71 @@ func (l *list) decrementOffset(n int) {
200202 }
201203}
202204
203−func (l *list) MoveUp(n int) {
205+// changeSelectedWhenNotVisible is called so we make sure we move to the next available selected that is visible
206+func (l *list) changeSelectedWhenNotVisible() tea.Cmd {
207+ var cmds []tea.Cmd
208+ start, end := l.viewPosition()
209+ currentPosition := 0
210+ itemWithinView := NotFound
211+ needsMove := false
212+
213+ for i, item := range l.items {
214+ rendered := l.renderedItems[i]
215+ itemStart := currentPosition
216+ // we remove 1 so that we actually have the row, e.x 1 row => height 1 => start 0, end 0
217+ itemEnd := itemStart + rendered.height - 1
218+ if itemStart >= start && itemEnd <= end {
219+ itemWithinView = i
220+ }
221+ if item.ID() == l.selectedItem {
222+ // item is completely above the viewport
223+ if itemStart < start && itemEnd < start {
224+ needsMove = true
225+ }
226+ // item is completely below the viewport
227+ if itemStart > end && itemEnd > end {
228+ needsMove = true
229+ }
230+ if needsMove {
231+ if focusable, ok := item.(layout.Focusable); ok {
232+ cmds = append(cmds, focusable.Blur())
233+ }
234+ l.renderedItems[i] = l.renderItem(item)
235+ } else {
236+ return nil
237+ }
238+ }
239+ if itemWithinView != NotFound && needsMove {
240+ newSelection := l.items[itemWithinView]
241+ l.selectedItem = newSelection.ID()
242+ if focusable, ok := newSelection.(layout.Focusable); ok {
243+ cmds = append(cmds, focusable.Focus())
244+ }
245+ l.renderedItems[itemWithinView] = l.renderItem(newSelection)
246+ break
247+ }
248+ currentPosition += rendered.height + l.gap
249+ }
250+ l.renderView()
251+ return tea.Batch(cmds...)
252+}
253+
254+func (l *list) MoveUp(n int) tea.Cmd {
204255 if l.direction == Forward {
205256 l.decrementOffset(n)
206257 } else {
207258 l.incrementOffset(n)
208259 }
260+ return l.changeSelectedWhenNotVisible()
209261}
210262
211−func (l *list) MoveDown(n int) {
263+func (l *list) MoveDown(n int) tea.Cmd {
212264 if l.direction == Forward {
213265 l.incrementOffset(n)
214266 } else {
215267 l.decrementOffset(n)
216268 }
269+ return l.changeSelectedWhenNotVisible()
217270}
218271
219272func (l *list) firstSelectableItemBefore(inx int) int {
@@ -239,10 +292,10 @@ func (l *list) moveToSelected() {
239292 return
240293 }
241294 currentPosition := 0
242− start, end := l.viewPosition(lipgloss.Height(l.rendered))
295+ start, end := l.viewPosition()
243296 for _, item := range l.renderedItems {
244297 if item.id == l.selectedItem {
245− if start <= currentPosition && currentPosition <= end {
298+ if start <= currentPosition && (currentPosition+item.height) <= end {
246299 return
247300 }
248301 // we need to go up
@@ -354,7 +407,7 @@ func (l *list) renderForward() tea.Cmd {
354407 currentIndex := 0
355408 for i, item := range l.items {
356409 currentIndex = i
357− if currentHeight > l.listHeight() {
410+ if currentHeight-1 > l.listHeight() {
358411 break
359412 }
360413 rendered := l.renderItem(item)
@@ -387,6 +440,7 @@ func (l *list) renderBackward() tea.Cmd {
387440 currentHeight := 0
388441 currentIndex := 0
389442 for i := len(l.items) - 1; i >= 0; i-- {
443+ fmt.Printf("rendering item %d\n", i)
390444 currentIndex = i
391445 if currentHeight > l.listHeight() {
392446 break
@@ -397,12 +451,13 @@ func (l *list) renderBackward() tea.Cmd {
397451 }
398452 // initial render
399453 l.renderView()
400− if currentIndex == len(l.items)-1 {
454+ if currentIndex == 0 {
401455 l.isReady = true
402456 return nil
403457 }
404458 return func() tea.Msg {
405459 for i := currentIndex; i >= 0; i-- {
460+ fmt.Printf("rendering item after %d\n", i)
406461 rendered := l.renderItem(l.items[i])
407462 l.renderedItems = append([]renderedItem{rendered}, l.renderedItems...)
408463 }
@@ -451,6 +506,9 @@ func (l *list) renderItems() tea.Cmd {
451506 l.selectLastItem()
452507 }
453508 }
509+ if l.direction == Forward {
510+ return l.renderForward()
511+ }
454512 return l.renderBackward()
455513}
456514
internal/tui/exp/list/list_test.go+159−38
@@ -12,6 +12,93 @@ import (
1212 "github.com/stretchr/testify/assert"
1313)
1414
15+func TestListPosition(t *testing.T) {
16+ type positionOffsetTest struct {
17+ dir direction
18+ test string
19+ width int
20+ height int
21+ numItems int
22+
23+ moveUp int
24+ moveDown int
25+
26+ expectedStart int
27+ expectedEnd int
28+ }
29+ tests := []positionOffsetTest{
30+ {
31+ dir: Forward,
32+ test: "should have correct position initially when forward",
33+ moveUp: 0,
34+ moveDown: 0,
35+ width: 10,
36+ height: 20,
37+ numItems: 100,
38+ expectedStart: 0,
39+ expectedEnd: 19,
40+ },
41+ {
42+ dir: Forward,
43+ test: "should offset start and end by one when moving down by one",
44+ moveUp: 0,
45+ moveDown: 1,
46+ width: 10,
47+ height: 20,
48+ numItems: 100,
49+ expectedStart: 1,
50+ expectedEnd: 20,
51+ },
52+ {
53+ dir: Backward,
54+ test: "should have correct position initially when backward",
55+ moveUp: 0,
56+ moveDown: 0,
57+ width: 10,
58+ height: 20,
59+ numItems: 100,
60+ expectedStart: 80,
61+ expectedEnd: 99,
62+ },
63+ {
64+ dir: Backward,
65+ test: "should offset the start and end by one when moving up by one",
66+ moveUp: 1,
67+ moveDown: 0,
68+ width: 10,
69+ height: 20,
70+ numItems: 100,
71+ expectedStart: 79,
72+ expectedEnd: 98,
73+ },
74+ }
75+ for _, c := range tests {
76+ t.Run(c.test, func(t *testing.T) {
77+ l := New(WithDirection(c.dir)).(*list)
78+ l.SetSize(c.width, c.height)
79+ items := []Item{}
80+ for i := range c.numItems {
81+ item := NewSelectsableItem(fmt.Sprintf("Item %d", i))
82+ items = append(items, item)
83+ }
84+ cmd := l.SetItems(items)
85+ if cmd != nil {
86+ cmd()
87+ }
88+
89+ if c.moveUp > 0 {
90+ l.MoveUp(c.moveUp)
91+ }
92+ if c.moveDown > 0 {
93+ l.MoveDown(c.moveDown)
94+ }
95+ start, end := l.viewPosition()
96+ assert.Equal(t, c.expectedStart, start)
97+ assert.Equal(t, c.expectedEnd, end)
98+ })
99+ }
100+}
101+
15102func TestBackwardList(t *testing.T) {
16103 t.Run("within height", func(t *testing.T) {
17104 t.Parallel()
@@ -19,7 +106,7 @@ func TestBackwardList(t *testing.T) {
19106 l.SetSize(10, 20)
20107 items := []Item{}
21108 for i := range 5 {
22− item := NewSimpleItem(fmt.Sprintf("Item %d", i))
109+ item := NewSelectsableItem(fmt.Sprintf("Item %d", i))
23110 items = append(items, item)
24111 }
25112 cmd := l.SetItems(items)
@@ -36,7 +123,7 @@ func TestBackwardList(t *testing.T) {
36123 t.Parallel()
37124 items := []Item{}
38125 for i := range 5 {
39− item := NewSimpleItem(fmt.Sprintf("Item %d", i))
126+ item := NewSelectsableItem(fmt.Sprintf("Item %d", i))
40127 items = append(items, item)
41128 }
42129 l := New(WithDirection(Backward), WithGap(1), WithSelectedItem(items[2].ID())).(*list)
@@ -54,7 +141,7 @@ func TestBackwardList(t *testing.T) {
54141 l.SetSize(10, 5)
55142 items := []Item{}
56143 for i := range 10 {
57− item := NewSimpleItem(fmt.Sprintf("Item %d", i))
144+ item := NewSelectsableItem(fmt.Sprintf("Item %d", i))
58145 items = append(items, item)
59146 }
60147 cmd := l.SetItems(items)
@@ -70,7 +157,7 @@ func TestBackwardList(t *testing.T) {
70157 l.SetSize(10, 5)
71158 items := []Item{}
72159 for i := range 10 {
73− item := NewSimpleItem(fmt.Sprintf("Item %d\nLine2", i))
160+ item := NewSelectsableItem(fmt.Sprintf("Item %d\nLine2", i))
74161 items = append(items, item)
75162 }
76163 cmd := l.SetItems(items)
@@ -86,7 +173,7 @@ func TestBackwardList(t *testing.T) {
86173 l.SetSize(10, 5)
87174 items := []Item{}
88175 for i := range 10 {
89− item := NewSimpleItem(fmt.Sprintf("Item %d", i))
176+ item := NewSelectsableItem(fmt.Sprintf("Item %d", i))
90177 items = append(items, item)
91178 }
92179 cmd := l.SetItems(items)
@@ -97,13 +184,13 @@ func TestBackwardList(t *testing.T) {
97184 l.MoveUp(1)
98185 golden.RequireEqual(t, []byte(l.View()))
99186 })
187+
100188 t.Run("should move at max to the top", func(t *testing.T) {
101− t.Parallel()
102189 l := New(WithDirection(Backward)).(*list)
103190 l.SetSize(10, 5)
104191 items := []Item{}
105192 for i := range 10 {
106− item := NewSimpleItem(fmt.Sprintf("Item %d", i))
193+ item := NewSelectsableItem(fmt.Sprintf("Item %d", i))
107194 items = append(items, item)
108195 }
109196 cmd := l.SetItems(items)
@@ -121,7 +208,7 @@ func TestBackwardList(t *testing.T) {
121208 l.SetSize(10, 5)
122209 items := []Item{}
123210 for i := range 10 {
124− item := NewSimpleItem(fmt.Sprintf("Item %d", i))
211+ item := NewSelectsableItem(fmt.Sprintf("Item %d", i))
125212 items = append(items, item)
126213 }
127214 cmd := l.SetItems(items)
@@ -138,7 +225,7 @@ func TestBackwardList(t *testing.T) {
138225 l.SetSize(10, 5)
139226 items := []Item{}
140227 for i := range 10 {
141− item := NewSimpleItem(fmt.Sprintf("Item %d", i))
228+ item := NewSelectsableItem(fmt.Sprintf("Item %d", i))
142229 items = append(items, item)
143230 }
144231 cmd := l.SetItems(items)
@@ -156,7 +243,7 @@ func TestBackwardList(t *testing.T) {
156243 l.SetSize(10, 5)
157244 items := []Item{}
158245 for i := range 10 {
159− item := NewSimpleItem(fmt.Sprintf("Item %d", i))
246+ item := NewSelectsableItem(fmt.Sprintf("Item %d", i))
160247 items = append(items, item)
161248 }
162249 cmd := l.SetItems(items)
@@ -167,15 +254,15 @@ func TestBackwardList(t *testing.T) {
167254 selectedInx := len(l.items) - 2
168255 currentItem := items[len(l.items)-1]
169256 nextItem := items[selectedInx]
170− assert.False(t, nextItem.(SimpleItem).IsFocused())
171− assert.True(t, currentItem.(SimpleItem).IsFocused())
257+ assert.False(t, nextItem.(SelectableItem).IsFocused())
258+ assert.True(t, currentItem.(SelectableItem).IsFocused())
172259 cmd = l.SelectItemAbove()
173260 if cmd != nil {
174261 cmd()
175262 }
176263
177264 assert.Equal(t, l.selectedItem, l.items[selectedInx].ID())
178− assert.True(t, l.items[selectedInx].(SimpleItem).IsFocused())
265+ assert.True(t, l.items[selectedInx].(SelectableItem).IsFocused())
179266
180267 golden.RequireEqual(t, []byte(l.View()))
181268 })
@@ -185,7 +272,7 @@ func TestBackwardList(t *testing.T) {
185272 l.SetSize(10, 5)
186273 items := []Item{}
187274 for i := range 10 {
188− item := NewSimpleItem(fmt.Sprintf("Item %d", i))
275+ item := NewSelectsableItem(fmt.Sprintf("Item %d", i))
189276 items = append(items, item)
190277 }
191278 cmd := l.SetItems(items)
@@ -210,7 +297,7 @@ func TestForwardList(t *testing.T) {
210297 l.SetSize(10, 20)
211298 items := []Item{}
212299 for i := range 5 {
213− item := NewSimpleItem(fmt.Sprintf("Item %d", i))
300+ item := NewSelectsableItem(fmt.Sprintf("Item %d", i))
214301 items = append(items, item)
215302 }
216303 cmd := l.SetItems(items)
@@ -227,7 +314,7 @@ func TestForwardList(t *testing.T) {
227314 t.Parallel()
228315 items := []Item{}
229316 for i := range 5 {
230− item := NewSimpleItem(fmt.Sprintf("Item %d", i))
317+ item := NewSelectsableItem(fmt.Sprintf("Item %d", i))
231318 items = append(items, item)
232319 }
233320 l := New(WithDirection(Forward), WithGap(1), WithSelectedItem(items[2].ID())).(*list)
@@ -245,7 +332,7 @@ func TestForwardList(t *testing.T) {
245332 l.SetSize(10, 5)
246333 items := []Item{}
247334 for i := range 10 {
248− item := NewSimpleItem(fmt.Sprintf("Item %d", i))
335+ item := NewSelectsableItem(fmt.Sprintf("Item %d", i))
249336 items = append(items, item)
250337 }
251338 cmd := l.SetItems(items)
@@ -261,7 +348,7 @@ func TestForwardList(t *testing.T) {
261348 l.SetSize(10, 5)
262349 items := []Item{}
263350 for i := range 10 {
264− item := NewSimpleItem(fmt.Sprintf("Item %d\nLine2", i))
351+ item := NewSelectsableItem(fmt.Sprintf("Item %d\nLine2", i))
265352 items = append(items, item)
266353 }
267354 cmd := l.SetItems(items)
@@ -277,7 +364,7 @@ func TestForwardList(t *testing.T) {
277364 l.SetSize(10, 5)
278365 items := []Item{}
279366 for i := range 10 {
280− item := NewSimpleItem(fmt.Sprintf("Item %d", i))
367+ item := NewSelectsableItem(fmt.Sprintf("Item %d", i))
281368 items = append(items, item)
282369 }
283370 cmd := l.SetItems(items)
@@ -288,13 +375,13 @@ func TestForwardList(t *testing.T) {
288375 l.MoveDown(1)
289376 golden.RequireEqual(t, []byte(l.View()))
290377 })
291− t.Run("should move at max to the top", func(t *testing.T) {
378+ t.Run("should move at max to the bottom", func(t *testing.T) {
292379 t.Parallel()
293380 l := New(WithDirection(Forward)).(*list)
294381 l.SetSize(10, 5)
295382 items := []Item{}
296383 for i := range 10 {
297− item := NewSimpleItem(fmt.Sprintf("Item %d", i))
384+ item := NewSelectsableItem(fmt.Sprintf("Item %d", i))
298385 items = append(items, item)
299386 }
300387 cmd := l.SetItems(items)
@@ -312,7 +399,7 @@ func TestForwardList(t *testing.T) {
312399 l.SetSize(10, 5)
313400 items := []Item{}
314401 for i := range 10 {
315− item := NewSimpleItem(fmt.Sprintf("Item %d", i))
402+ item := NewSelectsableItem(fmt.Sprintf("Item %d", i))
316403 items = append(items, item)
317404 }
318405 cmd := l.SetItems(items)
@@ -329,7 +416,7 @@ func TestForwardList(t *testing.T) {
329416 l.SetSize(10, 5)
330417 items := []Item{}
331418 for i := range 10 {
332− item := NewSimpleItem(fmt.Sprintf("Item %d", i))
419+ item := NewSelectsableItem(fmt.Sprintf("Item %d", i))
333420 items = append(items, item)
334421 }
335422 cmd := l.SetItems(items)
@@ -347,7 +434,7 @@ func TestForwardList(t *testing.T) {
347434 l.SetSize(10, 5)
348435 items := []Item{}
349436 for i := range 10 {
350− item := NewSimpleItem(fmt.Sprintf("Item %d", i))
437+ item := NewSelectsableItem(fmt.Sprintf("Item %d", i))
351438 items = append(items, item)
352439 }
353440 cmd := l.SetItems(items)
@@ -358,15 +445,15 @@ func TestForwardList(t *testing.T) {
358445 selectedInx := 1
359446 currentItem := items[0]
360447 nextItem := items[selectedInx]
361− assert.False(t, nextItem.(SimpleItem).IsFocused())
362− assert.True(t, currentItem.(SimpleItem).IsFocused())
448+ assert.False(t, nextItem.(SelectableItem).IsFocused())
449+ assert.True(t, currentItem.(SelectableItem).IsFocused())
363450 cmd = l.SelectItemBelow()
364451 if cmd != nil {
365452 cmd()
366453 }
367454
368455 assert.Equal(t, l.selectedItem, l.items[selectedInx].ID())
369− assert.True(t, l.items[selectedInx].(SimpleItem).IsFocused())
456+ assert.True(t, l.items[selectedInx].(SelectableItem).IsFocused())
370457
371458 golden.RequireEqual(t, []byte(l.View()))
372459 })
@@ -376,7 +463,7 @@ func TestForwardList(t *testing.T) {
376463 l.SetSize(10, 5)
377464 items := []Item{}
378465 for i := range 10 {
379− item := NewSimpleItem(fmt.Sprintf("Item %d", i))
466+ item := NewSelectsableItem(fmt.Sprintf("Item %d", i))
380467 items = append(items, item)
381468 }
382469 cmd := l.SetItems(items)
@@ -394,7 +481,28 @@ func TestForwardList(t *testing.T) {
394481 })
395482}
396483
397−type SimpleItem interface {
484+func TestListSelection(t *testing.T) {
485+ t.Run("should skip none selectable items initially", func(t *testing.T) {
486+ t.Parallel()
487+ l := New(WithDirection(Forward)).(*list)
488+ l.SetSize(100, 10)
489+ items := []Item{}
490+ items = append(items, NewSimpleItem("None Selectable"))
491+ for i := range 5 {
492+ item := NewSelectsableItem(fmt.Sprintf("Item %d", i))
493+ items = append(items, item)
494+ }
495+ cmd := l.SetItems(items)
496+ if cmd != nil {
497+ cmd()
498+ }
499+
500+ assert.Equal(t, items[1].ID(), l.selectedItem)
501+ golden.RequireEqual(t, []byte(l.View()))
502+ })
503+}
504+
505+type SelectableItem interface {
398506 Item
399507 layout.Focusable
400508}
@@ -403,15 +511,24 @@ type simpleItem struct {
403511 width int
404512 content string
405513 id string
514+}
515+type selectableItem struct {
516+ *simpleItem
406517 focused bool
407518}
408519
409−func NewSimpleItem(content string) SimpleItem {
520+func NewSimpleItem(content string) *simpleItem {
410521 return &simpleItem{
522+ id: uuid.NewString(),
411523 width: 0,
412524 content: content,
413− focused: false,
414− id: uuid.NewString(),
525+ }
526+}
527+
528+func NewSelectsableItem(content string) SelectableItem {
529+ return &selectableItem{
530+ simpleItem: NewSimpleItem(content),
531+ focused: false,
415532 }
416533}
417534
@@ -428,9 +545,6 @@ func (s *simpleItem) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
428545}
429546
430547func (s *simpleItem) View() string {
431− if s.focused {
432− return lipgloss.NewStyle().BorderLeft(true).BorderStyle(lipgloss.NormalBorder()).Width(s.width).Render(s.content)
433− }
434548 return lipgloss.NewStyle().Width(s.width).Render(s.content)
435549}
436550
@@ -444,19 +558,26 @@ func (s *simpleItem) SetSize(width int, height int) tea.Cmd {
444558 return nil
445559}
446560
561+func (s *selectableItem) View() string {
562+ if s.focused {
563+ return lipgloss.NewStyle().BorderLeft(true).BorderStyle(lipgloss.NormalBorder()).Width(s.width).Render(s.content)
564+ }
565+ return lipgloss.NewStyle().Width(s.width).Render(s.content)
566+}
567+
447568// Blur implements SimpleItem.
448−func (s *simpleItem) Blur() tea.Cmd {
569+func (s *selectableItem) Blur() tea.Cmd {
449570 s.focused = false
450571 return nil
451572}
452573
453574// Focus implements SimpleItem.
454−func (s *simpleItem) Focus() tea.Cmd {
575+func (s *selectableItem) Focus() tea.Cmd {
455576 s.focused = true
456577 return nil
457578}
458579
459580// IsFocused implements SimpleItem.
460−func (s *simpleItem) IsFocused() bool {
581+func (s *selectableItem) IsFocused() bool {
461582 return s.focused
462583}
internal/tui/exp/list/testdata/TestBackwardList/should_move_at_max_to_the_top.golden+1−1
@@ -2,4 +2,4 @@ Item 0
22Item 1
33Item 2
44Item 3
5−Item 4
5+│Item 4
internal/tui/exp/list/testdata/TestBackwardList/should_move_up.golden+1−1
@@ -2,4 +2,4 @@ Item 4
22Item 5
33Item 6
44Item 7
5−Item 8
5+│Item 8
internal/tui/exp/list/testdata/TestBackwardList/within_height.golden−2
@@ -1,7 +1,5 @@
11Item 0
22
3−Item 0
4−
53Item 1
64
75Item 2
internal/tui/exp/list/testdata/TestForwardList/should_move_at_max_to_the_top.golden → internal/tui/exp/list/testdata/TestForwardList/should_move_at_max_to_the_bottom.goldenrenamed+1−1
@@ -1,4 +1,4 @@
1−Item 5
1+│Item 5
22Item 6
33Item 7
44Item 8
internal/tui/exp/list/testdata/TestForwardList/should_move_down.golden+1−1
@@ -1,4 +1,4 @@
1−Item 1
1+│Item 1
22Item 2
33Item 3
44Item 4
internal/tui/exp/list/testdata/TestForwardList/within_height.golden−2
@@ -1,7 +1,5 @@
11│Item 0
22
3−│Item 0
4−
53Item 1
64
75Item 2
internal/tui/exp/list/testdata/TestListSelection/should_skip_none_selectable_items_initially.goldennew file+6
@@ -0,0 +1,6 @@
1+None Selectable
2+│Item 0
3+Item 1
4+Item 2
5+Item 3
6+Item 4