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

Ensure that there is always an active option in the Combobox #1279

Merged
merged 3 commits into from
Mar 29, 2022

Conversation

RobinMalfait
Copy link
Collaborator

@RobinMalfait RobinMalfait commented Mar 29, 2022

This PR ensures that the first non-disabled Combobox.Option will be the active one if no other active option exists.

This should improve the general UX of the Combobox component, because now you can search and immediately press Enter to choose that option instead of searching, pressing ArrowUp and then pressing Enter.

Some rules that apply:

  • If you have an active option already, that one should stay the active option as long as it can.
  • If no active option exists, but a Combobox.Option registers itself and is selected, then the first selected option will become the active one.
  • If you mosue out, then no active option should exist.
    • This will prevent weird jumps/scrolls if you leave the last option with your mouse and it jumps up to make the first option active.

This will be available in the next release.

You can already try it using:

  • npm install @headlessui/react@insiders or yarn add @headlessui/react@insiders.
  • npm install @headlessui/vue@insiders or yarn add @headlessui/vue@insiders.

This will ensure that the first non-disabled option is the active one if
no other active options exist. This means that any time you search for
something that the first result is the active one and you can just press
<kbd>Enter</kbd> to activate the option.

However, there are a few rules that we have to take into account:
- If you just open the Combobox, and there is a `selected`
  Combobox.Option, then we can't make the first option the active one.
  The first selected Combobox.Option has precedence over this one. This
  is important and rather tricky because Combobox.Option's register
  themselves at some point (later) in time.
- If you already have an active option, then that option should stay
  active. If it changes position, then the activeOptionIndex is adjusted
  to account for that.
- If you "mouse leave" an option, then no option should be active. It
  will be re-enabled the moment you start typing OR if you re-open the
  Combobox. Otherwise, it can happen that you are at the bottom of the
  list, mouse leave, and we scroll all the way back up to make the first
  item the active one which is not good for UX reasons.
@vercel
Copy link

vercel bot commented Mar 29, 2022

This pull request is being automatically deployed with Vercel (learn more).
To see the status of your deployments, click below or on the icon next to each commit.

headlessui-react – ./packages/playground-react

🔍 Inspect: https://vercel.com/tailwindlabs/headlessui-react/9h5Bsv4GT3HhwzVDqnKSYSrLXC2Q
✅ Preview: https://headlessui-react-git-ensure-active-combobox-option-tailwindlabs.vercel.app

headlessui-vue – ./packages/playground-vue

🔍 Inspect: https://vercel.com/tailwindlabs/headlessui-vue/94SD1kcxhUhjJZxhoQWHUoanhDcP
✅ Preview: https://headlessui-vue-git-ensure-active-combobox-option-tailwindlabs.vercel.app

@cabello
Copy link

cabello commented Mar 29, 2022

Great contribution! The behaviour is slightly odd:

  1. clear any active items using the mouse
  2. go to the input field
  3. filter
  4. first option is selected as expected
  5. arrow down stays in the first option, requiring another arrow down to go to the next one
Screen.Recording.2022-03-29.at.11.00.19.AM.mp4

@calthomson
Copy link

calthomson commented Mar 29, 2022

+1 to the behavior that @cabello explained, I am also experiencing this.

Edit: I can also recreate the behavior like so, so it may not just be related to this change:

  1. Open Combobox.
  2. Key down to the first option (without any filtering/searching). First option is selected.
  3. Key down again. First option remains selected.
  4. Key down again. Second option is now selected. Key down works from this point on.

TL;DR: It takes 3 key downs to get to the second option in the list, when it should take 2.

cc @RobinMalfait

@martinszeltins
Copy link

Super excited about this PR, can't wait to start using it. Hope the keyboard navigation issues get resolved before the release.

@RobinMalfait
Copy link
Collaborator Author

RobinMalfait commented Mar 29, 2022

@calthomson @cabello yikes, that happens when you work with selected values in your tests 😅 I could reproduce this in tests. Hold on, brb.

Edit: #1281

@aliemir
Copy link

aliemir commented Mar 29, 2022

Does not work at initial load when Combobox.Options's static is set as true. Not sure if it should though, but I think it should focus to the first index 😅

@martinszeltins
Copy link

Is this already released in stable?

@sgehrman
Copy link

sgehrman commented Apr 2, 2022

Xerox invented this like 40 years ago, and headless can't figure this out. :) Waiting for the new build.

@brampurnot
Copy link

is there also a way to deactivate this?

@cabello
Copy link

cabello commented Jun 29, 2022

Hi people, if you would like this to be deactivated use the emoji reactions, otherwise you are notifying everyone participating in this issue with non helpful "me too" comment.

@Sendrel
Copy link

Sendrel commented Jun 29, 2023

Are there any alternatives to remove this functionality? Kinda like a noInitialOptionSelected prop or a hack perhaps? I've tried manipulating data attributes (that handle the "activeness" of the option) of the respective html elements and it doesn't seem to work..

I am trying to replicate the "freeSolo" of material ui's autocomplete
https://mui.com/material-ui/react-autocomplete/#free-solo
I've already done the work.. the last thing that i need to do is just remove this initial option select.

@ScottEAdams
Copy link

To trick this into being "disabled" you can use the custom values from the docs:

https://headlessui.com/react/combobox#allowing-custom-values

<Combobox.Option value={{ text: yourSearchText }} className='hidden' />

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

Successfully merging this pull request may close these issues.

None yet

9 participants