@@ -864,6 +864,7 @@ func (l *list[T]) selectLastItem() {
866func (l *list[T]) firstSelectableItemAbove(inx int) int {
866func (l *list[T]) firstSelectableItemAbove(inx int) int {
867+ unfocusableCount := 0
867 for i := inx - 1; i >= 0; i-- {
868 for i := inx - 1; i >= 0; i-- {
868 if i < 0 || i >= len(l.items) {
869 if i < 0 || i >= len(l.items) {
@@ -873,14 +874,16 @@ func (l *list[T]) firstSelectableItemAbove(inx int) int {
873 if _, ok := any(item).(layout.Focusable); ok {
874 if _, ok := any(item).(layout.Focusable); ok {
877− if inx == 0 && l.wrap {
879+ if unfocusableCount == inx && l.wrap {
878 return l.firstSelectableItemAbove(len(l.items))
880 return l.firstSelectableItemAbove(len(l.items))
880 return ItemNotFound
882 return ItemNotFound
883func (l *list[T]) firstSelectableItemBelow(inx int) int {
885func (l *list[T]) firstSelectableItemBelow(inx int) int {
886+ unfocusableCount := 0
884 itemsLen := len(l.items)
887 itemsLen := len(l.items)
885 for i := inx + 1; i < itemsLen; i++ {
888 for i := inx + 1; i < itemsLen; i++ {
886 if i < 0 || i >= len(l.items) {
889 if i < 0 || i >= len(l.items) {
@@ -891,8 +894,9 @@ func (l *list[T]) firstSelectableItemBelow(inx int) int {
891 if _, ok := any(item).(layout.Focusable); ok {
894 if _, ok := any(item).(layout.Focusable); ok {
895− if inx == itemsLen-1 && l.wrap {
899+ if unfocusableCount == itemsLen-inx-1 && l.wrap {
896 return l.firstSelectableItemBelow(-1)
900 return l.firstSelectableItemBelow(-1)
898 return ItemNotFound
902 return ItemNotFound
@@ -1352,6 +1356,14 @@ func (l *list[T]) SelectItemAbove() tea.Cmd {
1353 // Pre-allocate with expected capacity
1357 // Pre-allocate with expected capacity
1354 cmds := make([]tea.Cmd, 0, 2)
1358 cmds := make([]tea.Cmd, 0, 2)
1359+ if newIndex > l.selectedItemIdx && l.selectedItemIdx > 0 && l.offset > 0 {
1360+ // this means there is a section above and not showing on the top, move to the top
1361+ newIndex = l.selectedItemIdx
1364+ cmds = append(cmds, cmd)
1355 if newIndex == 1 {
1367 if newIndex == 1 {
1356 peakAboveIndex := l.firstSelectableItemAbove(newIndex)
1368 peakAboveIndex := l.firstSelectableItemAbove(newIndex)
1357 if peakAboveIndex == ItemNotFound {
1369 if peakAboveIndex == ItemNotFound {
@@ -1383,12 +1395,16 @@ func (l *list[T]) SelectItemBelow() tea.Cmd {
1384 newIndex := l.firstSelectableItemBelow(l.selectedItemIdx)
1396 newIndex := l.firstSelectableItemBelow(l.selectedItemIdx)
1385 if newIndex == ItemNotFound {
1397 if newIndex == ItemNotFound {
1386− // no item above
1398+ // no item below
1387 return nil
1399 return nil
1389 if newIndex < 0 || newIndex >= len(l.items) {
1401 if newIndex < 0 || newIndex >= len(l.items) {
1390 return nil
1402 return nil
1404+ if newIndex < l.selectedItemIdx {
1405+ // reset offset when wrap to the top to show the top section if it exists
1392 l.prevSelectedItemIdx = l.selectedItemIdx
1408 l.prevSelectedItemIdx = l.selectedItemIdx
1393 l.selectedItemIdx = newIndex
1409 l.selectedItemIdx = newIndex
1394 l.movingByItem = true
1410 l.movingByItem = true