petyosi / react-virtuoso

The most powerful virtual list component for React
https://virtuoso.dev
MIT License
5.16k stars 299 forks source link

[BUG] GroupedVirtuoso - scrollIntoView doesn't scroll to item under group label #1019

Closed misha-erm closed 8 months ago

misha-erm commented 8 months ago

Describe the bug So I was trying to implement keyboard navigation for grouped list but noticed that item can go under group content and it won't be scrolled into view.

Here is a video of current behavior

https://github.com/petyosi/react-virtuoso/assets/8783498/e97816ee-41bc-47aa-a11a-3dc6e48231db

Reproduction Here is a sandbox

and a video of how it works on my side

https://github.com/petyosi/react-virtuoso/assets/8783498/96c48c09-208f-4b49-880d-1a403a885c91

To Reproduce Steps to reproduce the behavior:

  1. Navigate down so screen is scrolled
  2. Try to navigate up

Expected behavior scrollIntoView should take into account height of group content

Desktop (please complete the following information):

P.S. I've found a couple of similar issues but they all are closed so decided to open a new one

petyosi commented 8 months ago

The current implementation of scrollIntoView lets you scroll to items and groups - if I follow what you suggest, then groups would not be reachable - which I consider a valid scenario.

misha-erm commented 8 months ago

@petyosi I think there is some misunderstanding:

What should happen when I do scrollIntoView({index: 0})? Should first item of first group become visible? If yes then it's not working for me. Item stays below the group label and I'm stuck

image

In a contrast when I try scrollToIndex I never end in a situation like this. Item to which I scroll is visible

Thanks in advance for your assistance

misha-erm commented 8 months ago

Feels like it doesn't take into account groups size when calculating item's top.

I was able to workaround this by providing adjusted calculateViewLocation:

const calculateViewLocation: CalculateViewLocation = ({
  itemTop,
  itemBottom,
  viewportTop,
  viewportBottom,
  locationParams: {behavior, align, ...rest},
}) => {
  // where 32 is fixed height of my group content
  if (itemTop - 32 < viewportTop) {
    return {...rest, behavior, align: align != null ? align : "start"};
  }
  if (itemBottom > viewportBottom) {
    return {...rest, behavior, align: align != null ? align : "end"};
  }
  return null;
};