Implement virtual scroll component
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 53
- Forks
- 63
- Avg merge
- 2d 4h
- Merged PRs (30d)
- 15
Description
## Summary
Add a virtual scroll component similar to horizontal scroll which will act as a wrapper component for list style components, e.g. ic-menu, ic-data-table, ic-data-entity. But could also be used to wrap any lists any developers may have so will need it's own stories.
## 💬 Description
There are some good solutions for virtual scrolling components, however they're either React only, or they're not fleshed out enough, so it makes more sense for us to develop our own virtual scroll component than to import one.
The virtual scroll component should only render the visible nodes and be able to adjust with scrolling or tabbing/arrows.
It should also adjust to dynamic heights, many virtual scroll examples work out the visible nodes using a constant row height, but our menu options can be any height depending on html elements/labels/descriptions so we need to take that into account.
Some examples to take inspiration from:
- [React example with dynamic heights](https://codesandbox.io/s/virtual-scroll-dynamic-heights-using-hooks-6gmgu?file=/src/VirtualScroll.js:477-486)
- [Stencil example](https://github.com/mgnstudio7/stenciljs-virtual-scroll/blob/master/src/components/virtual-scroll/virtual-scroll.tsx) (this one probably wouldn't have been that bad to import but it hasn't been touched in 5-ish years and it has problems with duplicates)
- [Virtual list example that handles large data sets](https://github.com/sergi/virtual-list/blob/master/vlist.js)
- [Similar example to above but with dynamic heights](https://github.com/tbranyen/hyperlist/tree/master)
It's up to whoever develops it, however I do think it makes the most sense to slot ic-menu/ic-data-table/ic-data-entity into virtual scroll, like we do with horizontal scroll. A lot of the examples I found online seem to pass the list through as props, but I think it should be easy enough to access information about the array of items by doing something like we do in horizontal scroll:
```
this.itemsContainerEl = this.el.children[0] as HTMLElement;
this.items = Array.from(this.itemsContainerEl.children) as HTMLElement[];
```
A lot of the online examples also seem to complicate how to find the top of the container, but I think we should just be able to use getBoundingClientRect (see dialog, menu, tooltip, popover menu for examples of how to use this).
One thing I like from other examples is that they don't just render the nodes in view, but also a few above and below so that there are never any blank items showing.
## 💰 User value
This will help with sustainability and performance as only the visible nodes should be rendered in the dom, and these values will be updated as users scroll.
## 📚 User Stories
If relevant, describe the high-level functionality as user stories.
*As an* ICDS user:
*I need* a virtual scroll component
*So that* my large data set doesn't kill the performance of my app.
## 📝 Acceptance Criteria
If relevant, describe in full detail the different interactions and edge cases that the component or patterns needs to fulfil.
*Given* a user is using a keyboard to navigate
*When* they use a component wrapped in virtual scroll
*Then* there should be no difference in usage from when they have used it before it was wrapped.
*Given* a user is scrolling
*When* they scroll really fast in either direction
*Then* there should be not be any blank items, it should always render in time.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by inspecting the existing horizontal scroll component and its stories, then review ic-menu, ic-data-table, and ic-data-entity integration points. Check the dialog, menu, tooltip, and popover menu uses of getBoundingClientRect. Done means visible nodes remain rendered during fast scrolling and keyboard navigation behaves as before, including variable item heights.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- frontend, performance
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 38/100