open-ui icon indicating copy to clipboard operation
open-ui copied to clipboard

[selectmenu] List Virtualization

Open ZachHaber opened this issue 2 years ago • 1 comments

Currently List Virtualization (Windowing) or Infinite Scrolling is needed for large lists with select menus on any platform, however most component libraries don't implement it, which can drastically slow down page loading. For example, on one website I've been to, opening a "chapter select" select on mobile could cause the page to lock down for over a minute due to the sheer number of chapters, in which case the choice is between a less accessible custom component with virtualization, or just abandoning performance.

My main reason for bringing this up here is simply that without virtualization built in by default, we can end up with terrible performance which makes it incredibly complicated to use the built in components. And trying to implement virtualization on an existing accessible list can break accessibility due to the lack of integration.

Current State:

Angular does have a built in CDK for it. This doesn't have support for dynamic sized list items, which is problematic as you can't always know or be able to compute the size of your items in advance. From past attempts, it is also nearly impossible to get accessible keyboard control with a combobox using a virtual tabindex to keep the user on the input while maintaining the ability to select an option with arrow keys and enter.

There are several different React libraries (react-virtualized, react-window, react-virtual) for it as well, but unless it's built in with the component, it can be nearly impossible to use at all or get it working perfectly on a component.

Example:

Here's a React Example using Ariakit and react-virtual to render an accessible combobox. In this example, you can see the difference between a naïve "render everything" solution, an attempt using the css containment api (which doesn't do that much to help performance), and true list virtualization.

It takes a fair amount of knowledge to get it working at all, and react-window completely failed to work together.

The big issue here is that the focus loop fails - when you reach the end of the list and try and go past it, it should go to the other side of the list, but instead goes to start of what's currently rendered in the window. Also, in a similar issue, if you are holding down the arrow key to traverse the list, it will occasionally loop over again when the virtualization failed to keep up with the scrolling.


In an ideal world, the browser should handle this kind of performance enhancement on its own or provide a simple way to opt-in to get better performance (what I had hoped that the containment API would manage). But until that fine day, I ask that these new elements have accessible approaches for larger datasets.

ZachHaber avatar May 18 '22 17:05 ZachHaber