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 the caret is in a consistent position when syncing the Combobox.Input value #2568

Merged
merged 4 commits into from
Jun 30, 2023

Conversation

RobinMalfait
Copy link
Collaborator

@RobinMalfait RobinMalfait commented Jun 30, 2023

This PR will ensure that the caret is always in a consistent location once the input value is synced with the selected option. We will not do this while the user is typing because changing the position while typing will result in odd results.

Safari already kept the caret at the end, Chrome put the caret at the end but once you synced the value once the caret was in front of the text.

We will also only change the caret position if the position / selection didn't change in the meantime. For example, if you have code like this:

<Combobox.Input onFocus={e => e.target.select()} />

This will select all the text in the input field, if we just move the caret position without keeping this into account then we would undo this behaviour which is something we don't want to do.

Fixes: #2528

This will ensure the caret is always in a consistent location once the
input value has synced. We will _not_ do this while the user is typing
because changing the position while typing will result in odd results.

Safari already kept the caret at the end, Chrome put the caret at the
end but once you synced the value once the caret was in front of the
text.
@vercel
Copy link

vercel bot commented Jun 30, 2023

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
headlessui-react ✅ Ready (Inspect) Visit Preview 💬 Add feedback Jun 30, 2023 10:56am
headlessui-vue ✅ Ready (Inspect) Visit Preview 💬 Add feedback Jun 30, 2023 10:56am

Ensure that we only move the caret to the end, if the selection didn't
change in the meantime yet. For example when you have code like this:
```js
<Combobox.Input onFocus={e => e.target.select()} />
```

This will select all the text in the input field, if we just move the
caret position without keeping this into account then we would undo this
behaviour.
@peterbud
Copy link

peterbud commented Jul 3, 2023

What is the designated way to use a custom component or template using the "as" parameter for ComboBoxInput, as the documentation suggests? It seems to me that this change together using anything else than an input component leads to error like setSelectionRange is not a function.

@RobinMalfait
Copy link
Collaborator Author

RobinMalfait commented Jul 3, 2023

@peterbud you have to make sure that you forward all the incoming props and ensure the ref is set to an input field as well. E.g.:

import { forwardRef } from 'react'

const MyCustomInput = forwardRef((props, ref) => {
  return <input ref={ref} {...props} />
})

@peterbud
Copy link

peterbud commented Jul 4, 2023

@RobinMalfait thanks - I'm using vue, and it seems there is no similar thing to React's forwardRef.

@mattoni
Copy link

mattoni commented Sep 12, 2023

@RobinMalfait what if we're doing something like this for a tokenized multiselect?

<Combobox.Input
     as={isCreatable ? "span" : "input"}
     contentEditable />

It seems my comboboxes are all broken with this change after upgrading to latest with the error

L3.setSelectionRange is not a function

Is there a way to get this to function?

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.

Combobox - Typing does not replace existing value
3 participants