WICG/virtual-scroller

Bi-Directional Infinite Scrolling

daniel-nagy opened this issue · 3 comments

Some 1d collections need bi-directional infinite scrolling. A good example is a calendar that is initialized with today's date but allows the user to view past dates. Allowing negative indexes would be one way to implement this. Where 0 is today and -1 is yesterday and so on.

import { ItemSource } from 'virtual-scroller';
import { addDays, startOfToday } from 'date-fns';

new ItemSource({
  getLength(): number {
    return Infinity;
  },
  item(index: number): Date {
    return addDays(startOfToday(), index);
  }
});

Bi-directional infinite scrolling will add more complexity because views can be pushed onto the front of the virtual list. This means the view needs to be inserted and the scroll position needs to be adjusted in the same frame. I've implemented a prototype inspired by this Apple developer video.

In order to insert the view and adjust the scroll position in the same frame I had to come up with the concept of a synchronous scroll-view. This allows me to do the insert magic at the expense of moving scrolling to the main thread. This also means I have to implement my own scroll physics, which requires two implementations for both desktop and touch devices.

Also, for such bi-directional lists, the user probably doesn't want to see the scrollbar jumping around. One benefit of manually setting the scroll position is the scrollbar is never visible. A little bit of css magic can hide the scrollbar (e.g. a combination of padding and negative margins) but might require measuring the width of scrollbar for the device or just using a sufficiently large value.

Edit
Maybe this is a good use-case for layout-woklets?

The trick described here kinda works #111 (comment) but has a limit based on the browser's element max size restrictions.

You don't need to go that far. Negative scrolling is a must because of the chat. (you need to look back in time)