Virtualizer-scroll-to-element
- Dominant language
- TypeScript
- Stars
- 15.9k
- Forks
- 1.6k
- Avg merge
- 3d 9m
- Merged PRs (30d)
- 59
Description
### 🙋 Documentation Request
Issue Description
When using Virtualizer from the react-aria-components package together with ListBox, I need to scroll the list to a specific item (scroll-to-item). However, due to the current virtualization implementation, this is problematic because:
Virtualizer wraps the list items in a div that is inaccessible from outside.
The parent ListBox has a fixed height, but the inner div (where the items actually live) becomes much taller and does not respect the parent’s boundaries.
Hence, there’s no direct way to call scrollTo, scrollIntoView, etc. on the desired element within the Virtualizer. Below is a shortened version of my code.
Код
``` javascript
import cn from 'clsx'
import { useTranslations } from 'next-intl'
import { useCallback, useEffect, useMemo, useRef } from 'react'
import { Button, ListBox, ListBoxItem, ListLayout, Virtualizer } from 'react-aria-components'
import { useForm } from 'react-final-form'
import { MdCheck as IconCheck } from 'react-icons/md'
import { ListBoxPropTypes } from '@/components/_fields/FieldSelectNew/_types'
import { styles } from '@/components/_fields/FieldSelectNew/stylesFieldSelectNew'
import { compareWithWrongKeyboardLayout } from '@/utils/compareWithWrongKeyboardLayout/compareWithWrongKeyboardLayout'
import { useCheckViewport } from '@/utils/useCheckViewport/useCheckViewport'
export function ListBoxSelect({
handleChange,
inputValue,
isInputChange,
isOpen,
name,
optionId,
options,
rounded,
updateSelectState
}: ListBoxPropTypes): JSX.Element {
const { isMobile } = useCheckViewport()
const t = useTranslations()
const form = useForm()
const itemRefs = useRef>({})
const getItemRef = (id: string | number) => (node: HTMLButtonElement | null) => {
if (!node) return
itemRefs.current[id.toString()] = node
}
const matchedComposers = useMemo(() => {
if (isInputChange) {
return options?.filter((composer) =>
compareWithWrongKeyboardLayout({
compareText: composer?.name,
fromFirstIndex: true,
ignoreNonAlphanumeric: false,
search: inputValue
})
)
}
return []
}, [inputValue, isInputChange, options])
const data = isInputChange ? matchedComposers : options
const onSelectionChange = useCallback((optionValue: string, optionName: string) => {
handleChange?.(optionValue)
form.batch(() => {
form.change(name, optionValue)
})
updateSelectState('optionId', optionValue)
updateSelectState('inputValue', optionName)
updateSelectState('isOpen', false)
}, [form, name, handleChange, updateSelectState])
useEffect(() => {
if (isOpen && optionId) {
setTimeout(() => {
const refEl = itemRefs.current[optionId.toString()]
if (refEl) {
// Attempt to scroll to the required element
refEl.scrollIntoView({
behavior: 'instant',
block: 'center'
})
}
}, 0)
}
}, [isOpen, optionId])
return (
(
{t('common.select.emptyText')}
)}
>
{(item) => (
{({ isSelected }) => (
onSelectionChange(item?.id, item?.name)}
ref={getItemRef(item.id)}
>
{item?.name}
{isSelected && (
)}
)}
)}
)
}
```
Current Behavior
The list is virtualized.
The scrollIntoView() method is called, but it does not work as expected: the element does not scroll into the correct position within the list, likely because the virtualized container is “taller” and not strictly bound to the parent’s boundaries.
Expected Behavior
Ability to control scrolling within the virtualized list: for example, “scroll” to the needed item by optionId or call a method/callback that does it inside the Virtualizer.
Optionally, extend or add a built-in API that allows passing scrollToItem() or a similar method without having to go through the inner div.
Question
Will Virtualizer (or the relevant part of the library) include the ability to scroll to a specific item (scroll-to-item) in the near future? If so, is there any timeframe or example of how to achieve this with the library?
I would greatly appreciate any advice or ready-made solution on how to implement “scroll to item” functionality using Virtualizer.
Additional Information
React: 19.0.0
react-aria-components: 1.7.1
OS: MacOS
Browsers: Chrome
P.S. Thank you in advance for any help or guidance on how to implement this feature!
### 🧢 Your Company/Team
_No response_
Contributor guide
Assessment
This issue has not been assessed yet.