adobe / adobe/react-spectrum

Virtualizer-scroll-to-element

Open
#7,986 3 comments 0 reactions 0 assignees View on GitHub
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

Image

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

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.