Skip to content

Collections do not scroll items into view within the browser viewport with keyboard #2766

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
majornista opened this issue Jan 21, 2022 · 0 comments · Fixed by #3899
Closed

Comments

@majornista
Copy link
Collaborator

majornista commented Jan 21, 2022

🐛 Bug Report

When the bounds of a virtualized collection extend beyond the browser viewport, and setting focus to an item within the collection that is out of view, the browser will not scroll the focused item into view.

🤔 Expected Behavior

An item receiving focus in a virtualized collection should not only scroll the item into view within the collection, but it should scroll the item into view within the browser as well.

😯 Current Behavior

  1. Open https://reactspectrum.blob.core.windows.net/reactspectrum/0661785f30971bdbcbd291282b26836cf272c3f8/storybook/iframe.html?id=listbox--async-loading&viewMode=story
  2. Reduce the inner height of the browser window to be less than the height of the ListBox within the story, ~200px should be good.
  3. Tab to set keyboard focus to the first Item within the ListBox.
  4. Use ArrowDown to scroll until you focus an Item within the ListBox that is outside of the browser viewport.
  5. Notice that the browser does not automatically scroll the document.body to bring the focused Item into view.

💁 Possible Solution

Add the following to useVirtualizer method in @react-aria/virtualizer/src/Virtualizer.tsx:

  // Define an IntersectionObserver to evaluate whether the browser should scroll the element receiving focus into view.
  let intersectionObserver = useMemo(() => {
    const intersectionObserverOptions:IntersectionObserverInit = {
      root: undefined,
      rootMargin: '0px', 
      threshold: 1
    };

    const scrollIntoViewOptions:ScrollIntoViewOptions = {
      behavior: 'auto',
      block: 'nearest',
      inline: 'nearest'
    };

    const intersectionObserverCallback = (entries:Array<IntersectionObserverEntry>, observer:IntersectionObserver) => {
      entries.forEach(entry => {
        if (!entry.isIntersecting) {
          entry.target.scrollIntoView(scrollIntoViewOptions);
        }
        observer.unobserve(entry.target);
      });
    };

    return new IntersectionObserver(intersectionObserverCallback, intersectionObserverOptions);
  }, []);

Then at the end of the onFocus method, add the following after updating isFocusWithin.current:

    // Evaluate whether the browser should scroll to bring element receiving focus into view.
    if (isFocusWithin.current) {
      intersectionObserver.observe(e.target);
    }

🔦 Context

This bug was reported by a team using a static TableView that noticed when the TableView was larger than the browser viewport, focusing a row would not cause the browser to scroll it into view.

💻 Code Sample

🌍 Your Environment

Software Version(s)
react-spectrum @react-aria/[email protected]
Browser Chrome Version 97.0.4692.71 (Official Build) (x86_64)
Operating System macOS Version 12.1 (21C52)

🧢 Your Company/Team

Adobe/Accessibility Adobe/Admin_Console

🕷 Tracking Issue (optional)

Jira issue A11Y-5009 and TRON-8092

@majornista majornista self-assigned this Jan 21, 2022
majornista added a commit that referenced this issue Jan 21, 2022
…owser viewport

Add IntersectionObserver to detect whether or not a focused item is visible within the browser window, and if not scroll it into view.
majornista added a commit that referenced this issue Jan 21, 2022
jest does not recognize IntersectionObserver.
majornista added a commit that referenced this issue Feb 14, 2022
Update focusSafely method to account for focusing an element safely after a pointer event on another element.
majornista added a commit that referenced this issue Feb 24, 2022
…owser viewport

Add IntersectionObserver to detect whether or not a focused item is visible within the browser window, and if not scroll it into view.
majornista added a commit that referenced this issue Feb 24, 2022
jest does not recognize IntersectionObserver.
majornista added a commit that referenced this issue Feb 24, 2022
Update focusSafely method to account for focusing an element safely after a pointer event on another element.
@matthewdeutsch matthewdeutsch moved this from To Groom to To Investigate / Verify in RSP Component Milestones Aug 17, 2022
@matthewdeutsch matthewdeutsch moved this from To Investigate / Verify to To Groom in RSP Component Milestones Aug 17, 2022
@LFDanLu LFDanLu moved this from To Groom to Waiting for Sprint in RSP Component Milestones Aug 24, 2022
@dannify dannify changed the title Virtualizer does not scroll items into view within the browser viewport Collections do not scroll items into view within the browser viewport with keyboard Nov 9, 2022
@matthewdeutsch matthewdeutsch assigned LFDanLu and unassigned majornista Nov 9, 2022
@LFDanLu LFDanLu moved this from 📋 Waiting for Sprint to 🏗 In Progress in RSP Component Milestones Nov 22, 2022
@LFDanLu LFDanLu moved this from 🏗 In Progress to 👀 In Review in RSP Component Milestones Jan 17, 2023
@github-project-automation github-project-automation bot moved this from 👀 In Review to ✅ Done in RSP Component Milestones Feb 1, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment