Reach-ui: Navigating to an option in listbox doesn't reveal it if popover is scrollable

Created on 20 Jul 2020  路  2Comments  路  Source: reach/reach-ui

馃悰 Bug report

Current Behavior

When setting a max-height and overflow on a Listbox popover, navigating to an option with up/down arrows or typing the first letters of the option should reveal it if it is not in view.

Expected behavior

When setting a max-height on the popover, navigating to an option brings this option into view, like in this example.

Reproducible example

CodeSandbox example

Suggested solution(s)

I just started reading the code of the component, I suppose it's something not implemented yet in the state machine?
Will gladly help once I get more into the code!

Your environment

| Software | Name(s) | Version |
| ---------------- | ------- | ------- |
| Reach Package | listbox | 10.5.0 |
| React | |16.12.0 |
| Browser | Firefox | 78 |

Help Wanted Stale Enhancement

Most helpful comment

For anyone facing this, this worked for me:

const ListboxList: React.FC<ListBox.ListboxListProps> = (props) => {
    const {selectedOptionRef, isExpanded, highlightedOptionRef} = ListBox.useListboxContext()

    // Ensure that the selected item is in view when opening the popover
    React.useEffect(() => {
        if (selectedOptionRef.current && isExpanded) {
            selectedOptionRef.current.scrollIntoView({block: 'nearest'})
        }
    }, [isExpanded])

    // Ensure that the highlighted item is in view at all times when using keyboard
    React.useEffect(() => {
        const ensureHighlightedInView = () => {
            if (highlightedOptionRef.current) {
                highlightedOptionRef.current.scrollIntoView({block: 'nearest'})
            }
        }

        window.addEventListener('keydown', ensureHighlightedInView)
        return () => {
            window.removeEventListener('keydown', ensureHighlightedInView)
        }
    }, [])

    return <StyledListboxList {...props} />
}

All 2 comments

This is not implemented because users may have different needs for handling scroll logic inside their menu component, and we don't want to be too opinionated here. That said, it should definitely be achievable in a wrapped component. I'd love to add an example to the docs for this need. Help is gladly welcome, just let me know if you run into any blockers as you dig in!

For anyone facing this, this worked for me:

const ListboxList: React.FC<ListBox.ListboxListProps> = (props) => {
    const {selectedOptionRef, isExpanded, highlightedOptionRef} = ListBox.useListboxContext()

    // Ensure that the selected item is in view when opening the popover
    React.useEffect(() => {
        if (selectedOptionRef.current && isExpanded) {
            selectedOptionRef.current.scrollIntoView({block: 'nearest'})
        }
    }, [isExpanded])

    // Ensure that the highlighted item is in view at all times when using keyboard
    React.useEffect(() => {
        const ensureHighlightedInView = () => {
            if (highlightedOptionRef.current) {
                highlightedOptionRef.current.scrollIntoView({block: 'nearest'})
            }
        }

        window.addEventListener('keydown', ensureHighlightedInView)
        return () => {
            window.removeEventListener('keydown', ensureHighlightedInView)
        }
    }, [])

    return <StyledListboxList {...props} />
}
Was this page helpful?
0 / 5 - 0 ratings