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

[useAutocomplete] Add support for groupedOptions to always be returned regardless of focus #269

Open
martin-slalom opened this issue Mar 21, 2024 · 10 comments
Labels
component: autocomplete This is the name of the generic UI component, not the React module! enhancement This is not a bug, nor a new feature

Comments

@martin-slalom
Copy link

martin-slalom commented Mar 21, 2024

Summary

I have a need to build my own autocomplete that renders the groupedOptions/list options and the input in a single popover. The only issue I'm running into with useAutocomplete to build out this component out is that the groupedOptions is changed to an empty array when the input is no longer focused. My proposal would be to add a prop to the useAutocomplete that would override this functionality to allow the list to be rendered regardless of the input being focused. This would give the developer more freedom to build out the dropdown list.

Examples

Example use case, I need to create an account selector that shows the Currently selected account but when you click the name it opens a Popover with a search input and the list of accounts. As the user types it filters and acts just like the autocomplete where the user can select a value and it will then navigate them.

I've thrown together, a very rough, example of this. You'll notice that when you click "The Godfather" in the blue bar a popover opens and the list reads "no results". This is because the input isn't focused, then when the input is focused the list appears. We can set autoFocus on the input and set openOnFocus on the useAutocomplete however, when the user selects an option from the list the focus is then changed to that item, away from the input and thus the list closes (reverting to "no results").

I propose an "override" prop on the useAutocomplete component to give the developer freedom to receive the list without worrying about the focus state of the input.

  const popupOpen = open && !readOnly;

-  const filteredOptions = popupOpen
+  const filteredOptions = ignoreFocus || popupOpen
    ? filterOptions(
        options.filter((option) => {
          if (
            filterSelectedOptions &&
            (multiple ? value : [value]).some(
              (value2) => value2 !== null && isOptionEqualToValue(option, value2),
            )
          ) {
            return false;
          }
          return true;
        }),
        // we use the empty string to manipulate `filterOptions` to not filter any options
        // i.e. the filter predicate always returns true
        {
          inputValue: inputValueIsSelectedValue && inputPristine ? '' : inputValue,
          getOptionLabel,
        },
      )
    : [];

Motivation

No response

Search keywords: useAutocomplete

@martin-slalom martin-slalom added the status: waiting for maintainer These issues haven't been looked at yet by a maintainer label Mar 21, 2024
@zannager zannager added the component: autocomplete This is the name of the generic UI component, not the React module! label Mar 22, 2024
@ZeeshanTamboli
Copy link
Member

@martin-slalom I'm having trouble understanding your issue. Your CodeSandbox example, although somewhat unclear, doesn't seem to be behaving as you described. If the list isn't being shown and the input isn't focused, why do you require groupedOptions? Displaying "No results" should be incorporated into the options list itself rather than serving as a placeholder for the input. Additionally, you should render the listbox only when there are groupedOptions available.

@ZeeshanTamboli ZeeshanTamboli added status: waiting for author Issue with insufficient information and removed status: waiting for maintainer These issues haven't been looked at yet by a maintainer labels Mar 29, 2024
@martin-slalom
Copy link
Author

martin-slalom commented Mar 29, 2024

@ZeeshanTamboli
My apologies, I figured out the issue I've updated the example. But the point I was trying to demonstrate in the demo is that for my use case the list should be shown when the popover is opened regardless if the user has focused the input or not. The only way to get the list to show up is if the input is focused, as soon as it's unfocused it goes away.

For a "traditional" autocomplete I 100% agree with you that the listbox should only be rendered when groupedOptions are available (aka the input is focused). However for my use case it's not a traditional autocomplete the input and groupedOptions need to be rendered together at the same time in say a popover, card, dialog, etc. This is not possible with the current state of the useAutocomplete hook only because of the "open" logic that reverts the filteredList (aka groupedOptions) back to [] once focus state isn't on the input. This including using tab to select from filtered options since the focus is now on the menu items.

My feature request is to add a prop that could be toggled on to give the developer the ability to overwrite that resetting to "[]" so that they may utilize the hook in non-traditional ways.

2024-03-29 09 59 21

@github-actions github-actions bot added status: waiting for maintainer These issues haven't been looked at yet by a maintainer and removed status: waiting for author Issue with insufficient information labels Mar 29, 2024
@ZeeshanTamboli
Copy link
Member

ZeeshanTamboli commented Mar 30, 2024

If you're not building an autocomplete feature, it's best not to utilize the useAutocomplete hook. Instead, consider creating your own custom hook tailored to your specific requirements. Could you try focusing the input programmatically when the popup is opened?

I don't believe we'll add a prop for this. It doesn't seem necessary to me. I'm closing this issue.

@ZeeshanTamboli ZeeshanTamboli added status: waiting for author Issue with insufficient information and removed status: waiting for maintainer These issues haven't been looked at yet by a maintainer status: waiting for author Issue with insufficient information labels Mar 30, 2024
@ZeeshanTamboli ZeeshanTamboli closed this as not planned Won't fix, can't repro, duplicate, stale Mar 30, 2024
@martin-slalom
Copy link
Author

martin-slalom commented Apr 1, 2024

So the thing is @ZeeshanTamboli my feature is functionally an autocomplete in every regard. It's just not visually a "traditional autocomplete" where the dropdown is triggered by focusing an input, rather the input and dropdown live together in a popover that's triggered by the clicking another element. It has the same need for everything that a traditional autocomplete would would have EXCEPT the clearing of the dropdown list once the input loses focus. I'm confused how that is not shown via my example, could you please explain how the component in the codesandbox is not an autocomplete?

Additionally, focusing the input programmatically when the popup is opened does work until you use the "tab" functionality to select an item from the list since at that point the input would loose focus for that of the list item button, as you can see in the example.

2024-04-01 09 14 25

@ZeeshanTamboli
Copy link
Member

In the autocomplete, we use the combobox W3 ARIA pattern. According to this pattern, the popover is hidden by default and requires a trigger to be opened.

@martin-slalom
Copy link
Author

In the autocomplete, we use the combobox W3 ARIA pattern. According to this pattern, the popover is hidden by default and requires a trigger to be opened.

I feel like my example/use case still follows that pattern as well, the popover/list is hidden by default and exposed via a trigger as well. It's just that trigger in this case isn't an input it's a div. The user can filter the list via typing in the input, "hover" over options via arrow/tab keys, and selecting one by clicking or pressing enter. Other features like list grouping can also be used.

Maybe there's some confusion, especially since the tag is "component:Autocomplete", I'm not suggesting any changes to the Mui Autocomplete component. I'm merely suggesting an enhancement to the useAutocomplete hook. In my use case, yes a bit of a nontraditional pattern but, the functionality the hook provides does 99.5% of exactly what is needed, aside from the whole resetting of the groupedOptions when the input loses focus.

My requested change would have no effect at all on the Mui Autocomplete at all. It would only add flexibility/functionality to useAutocomplete hook. It wouldn't even need to be exposed via Autocomplete's props (and probably shouldn't) and only be available for useAutocomplete.

@ZeeshanTamboli
Copy link
Member

Both Material UI's Autocomplete and Joy UI's Autocomplete utilize the useAutocomplete internally, so this change could impact them.

I feel like my example/use case still follows that pattern as well, the popover/list is hidden by default and exposed via a trigger as well. It's just that trigger in this case isn't an input it's a div.

Okay, I noticed the following statement in the ARIA docs as well: It is displayed when the Down Arrow key is pressed or the Open button is activated. Considering that a button trigger can open the list, I'll go ahead and open the issue. Feel free to propose a solution by creating a PR, but please make sure it doesn't impact the Material UI and Joy UI Autocompletes.

@ZeeshanTamboli ZeeshanTamboli reopened this Apr 6, 2024
@ZeeshanTamboli
Copy link
Member

ZeeshanTamboli commented Apr 6, 2024

Additionally, please keep in mind that the useAutocomplete functionality resides in Base UI within this repository (Core repo). However, we're planning to remove it from here. We're actively developing Base UI in a separate repository - https://github.com/mui/base-ui, so any changes must also be applied there. I'm also transferring this issue to Base UI repo.

@ZeeshanTamboli ZeeshanTamboli added the enhancement This is not a bug, nor a new feature label Apr 6, 2024
@ZeeshanTamboli ZeeshanTamboli transferred this issue from mui/material-ui Apr 6, 2024
@martin-slalom
Copy link
Author

So should I open a PR against the Base-UI repo as well as Material-ui repo?

@ZeeshanTamboli
Copy link
Member

So should I open a PR against the Base-UI repo as well as Material-ui repo?

You can open it only in the Base UI repo. Version 1 of Base UI is coming soon, and the Base UI-related code will be removed from the Material UI repo.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
component: autocomplete This is the name of the generic UI component, not the React module! enhancement This is not a bug, nor a new feature
Projects
None yet
Development

No branches or pull requests

4 participants