Skip to content
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鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Combobox] Tab sequence gets stuck in popover interactive elements #545

Closed
indiesquidge opened this issue Apr 10, 2020 · 6 comments
Closed
Labels
Status: Investigation Type: Bug Something isn't working

Comments

@indiesquidge
Copy link
Collaborator

馃悰 Bug report

Current Behavior

When tabbing to interactive elements in the popover, the tab sequence gets stuck in the popover

combobox-no-tab-escape-from-popover

Compare this to the popover itself, which does not track the tab sequence.

popover-tab-behavior

Interestingly, the tab sequence issue is not reproducible on the website examples, despite creating a clean slate with cd website/ && rm -rf node_modules && yarn && yarn dev.

combobox-website

Expected behavior

There is nothing mentioned on WAI ARIA about trapping focus in the listbox popover, so I would expect the tab sequence to predictably follow the browser default sequence, i.e. how the current Reach UI popover component behaves (as shown above).

Reproducible example

CodeSandbox Template

Running the Storybook examples locally will also reproduce this issue

Suggested solution(s)

Even after tinkering locally, its not clear to me why the tab sequence is trapped in the combobox popover (and also why it isn't on the website examples).

Additional context

Your environment

Software Name(s) Version
Reach Package combobox 0.10.0
React - 16.13.0
Browser Chrome 80.0.3987.163
Assistive tech - -
Node - v13.12.0
npm/yarn yarn 1.22.4
Operating System macOS 10.15.4
@indiesquidge indiesquidge changed the title [Combobox] Unexpected keyboard bugs [Combobox] Tab sequence gets stuck in popover interactive elements Apr 10, 2020
@indiesquidge
Copy link
Collaborator Author

indiesquidge commented Apr 10, 2020

This is perhaps a separate issue, but a fresh build of the website also warns that certain @reach/utils aren't exported (even though they are, and browsing my local node_modules even shows that they are). Something feels a bit off about the build of the website locally (or I'm just setting up the dev env wrong), which could explain why I can't reproduce the combobox issue on the website examples.

Screen Shot 2020-04-10 at 2 36 35 PM

@chaance chaance added the Status: Unconfirmed Bug reports without a repro, not yet confirmed label Apr 11, 2020
@reach reach deleted a comment from enforce-template-use bot Apr 13, 2020
@chaance chaance added Status: Investigation Type: Bug Something isn't working and removed Status: Unconfirmed Bug reports without a repro, not yet confirmed labels Apr 13, 2020
@chaance
Copy link
Member

chaance commented Apr 13, 2020

There has been some discussion on how we handle this by default in various components. All of the ARIA examples I've seen that implement popovers with interactive content do in fact lock focus in the popover, though some UI specs don't mention it explicitly (particularly if the example doesn't use nested tabbable elements). My general feeling is aligned with yours here, and that's the default approach taken in listbox currently. I would like to get some more feedback from users in the a11y community here.

That said, no idea why the behavior wouldn't be consistent between the docs and local build. Haven't had a problem building the site locally on my end or in CI 馃

@raunofreiberg
Copy link
Contributor

raunofreiberg commented May 18, 2020

I think the root of the problem lies in Popover. Hear me out!

All of the examples where tab sequence is not disrupted have focusable elements before and after the component.

I added a sibling input element to the reproducible example and the tab sequence is correct:
https://codesandbox.io/s/hardcore-dewdney-0htlo
gif

Or, using portal={false} on ComboboxPopover also fixes the problem since Popover is not used: https://codesandbox.io/s/distracted-hofstadter-9633t


Alas, if you reduce the Popover example down to a single textarea, the same issue appears:
https://codesandbox.io/s/new-darkness-uipul

I'll try to take a closer look later, but on first guess, the devil is somewhere here:

function useSimulateTabNavigationForReactTree<

@raunofreiberg
Copy link
Contributor

I dunno if this makes sense, but these changes to focusLastTabbableInPopover seem to fix tabbing back and forth between the trigger and elements inside the Popover.

function focusLastTabbableInPopover(event: KeyboardEvent) {
  const elements = popoverRef.current && tabbable(popoverRef.current);

+  // The actual last tabbable should be the trigger.
+  // We push it manually to the array because it is outside of the portal of popover.
+  triggerRef.current && elements?.push(triggerRef.current);

  const last = elements && elements[elements.length - 1];

  if (last) {
    event.preventDefault();
    last.focus();
  }
}

gif

michaeldfoley added a commit to michaeldfoley/reach-ui that referenced this issue Jun 6, 2020
michaeldfoley added a commit to michaeldfoley/reach-ui that referenced this issue Jun 6, 2020
@michaeldfoley
Copy link
Contributor

I too believe that the issue relates to Popover, specifically cases where the targetRef is the last tabbable element outside the popover. When this is the case, getElementAfterTrigger returns the first tabbable element inside the portal causing the focus to stay trapped inside the popover. What we want is for getElementAfterTrigger to return an element only if it is not inside the popover.

I submitted a PR (#609) that should address the issue. I recreated the original example referenced in this issue and the focus now moves outside the popover as expected.

@chaance
Copy link
Member

chaance commented Jun 15, 2020

Should be fixed in 0.10.4. Please let me know if you continue to have issues.

@chaance chaance closed this as completed Jun 15, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Status: Investigation Type: Bug Something isn't working
Projects
None yet
Development

No branches or pull requests

4 participants