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’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

useListNavigation moves focus into list unexpectedly when an item is dynamically removed from the list #2883

Closed
mihkeleidast opened this issue May 2, 2024 · 8 comments · Fixed by #2914
Labels
bug Something is not working.

Comments

@mihkeleidast
Copy link
Contributor

Describe the bug

I'm building a non-floating Listbox component with useListNavigation and useTypeahead hooks. One possibility there is that items can be added/removed dynamically. However, if that is done, useListNavigation sometimes moves focus unexpectedly.

To Reproduce

https://codesandbox.io/p/sandbox/floating-ui-react-listbox-with-composable-children-g524xl?file=%2Fsrc%2FApp.tsx%3A89%2C40

Since the focus issue is most problematic with keyboard navigation, it is recommended to use keyboard nav and selection for the steps.

  1. Move into listbox, select third option ("Watermelon")
  2. Move out of listbox, to "toggle item" button
  3. Toggle the item on, then off
  4. See that focus is moved to "Watermelon" option unexpectedly.

Expected behavior

Focus should stay on the button.

Context:

  • OS: Windows
  • Browser: Edge
  • Version: 124

Additional context

I think useListNavigation currenly attempts to focus the selectedIndex item if it changes, but it does not check whether the focus is inside the list.

There is also another issue visible there, that when dynamically adding an item to the selected index position. I would expect that the selected item remains the same, whereas right now it changes to the dynamic item. But this may be a misconfiguration issue and can be worked around, as it does not happen in my own codebase.

@mihkeleidast mihkeleidast changed the title useListNavigation moves focus into list unexpectedly when an item is dynamically added/removed to/from the selected index position useListNavigation moves focus into list unexpectedly when an item is dynamically removed from the list May 2, 2024
@atomiks
Copy link
Collaborator

atomiks commented May 2, 2024

I can't seem to reproduce from the steps provided - focus stays on the button.

@mihkeleidast
Copy link
Contributor Author

Hmm, here's a video, definitely happens for me:

screen-capture.webm

@mihkeleidast
Copy link
Contributor Author

From tracing the focus, it seems to come from here: https://github.com/floating-ui/floating-ui/blob/master/packages/react/src/hooks/useListNavigation.ts#L457

Which makes sense, as that effect also runs on selectedIndex change, which happens if the toggled item is before the selected item.

@mihkeleidast
Copy link
Contributor Author

How about this for a repro, it's a bit less realistic but should show the same issue: https://codesandbox.io/p/sandbox/floating-ui-react-listbox-with-composable-children-forked-p32x5d

Prerequisite is that activeIndex is not null, this essentially happens whenever you've focused into the listbox at least once, but for demo purposes I set the initial value as 1.

  1. Focus button with keyboard
  2. Press button
  3. Focus moves to "Blueberry" option, but it should not - this is essentially "controlled" selectedIndex behavior, should select option without moving focus.

@atomiks
Copy link
Collaborator

atomiks commented May 2, 2024

That one does reproduce by moving focus into the listbox, not sure why the original demo doesn't

@atomiks
Copy link
Collaborator

atomiks commented May 19, 2024

Okay so I manged to reproduce the original demo now.

From what I can see, this is user error because you're reading a ref in render which is forbidden by React. If you refactor selectedLabel to selectedIndex so that a ref isn't being read in render, the problem doesn't occur.

https://codesandbox.io/p/sandbox/floating-ui-react-listbox-with-composable-children-forked-5wtms5

@atomiks atomiks closed this as not planned Won't fix, can't repro, duplicate, stale May 19, 2024
@mihkeleidast
Copy link
Contributor Author

mihkeleidast commented May 19, 2024

@atomiks fair point about my original repro, but my second repro with controlling the selectedIndex value (i.e. https://codesandbox.io/p/sandbox/floating-ui-react-listbox-with-composable-children-forked-p32x5d) does not do that, unless I'm missing something? Do you think it's reasonable to move focus into the listbox when selectedIndex changes by some means (in a real world usecase this may just be data updating in a polling fetch, or something like that).

@atomiks
Copy link
Collaborator

atomiks commented May 20, 2024

Oh good point, didn't verify the second one too. From what I can see, simply making selectedIndex non-reactive fixes the issue. I'll make a PR in a sec

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something is not working.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants