Robin Malfait 4ed69f640c Keep focus inside of the <ComboboxInput /> component (#3073)
* bail the refocus if focus is already on the correct element

* use `mousedown` instead of `click` event

The `mousedown` event happens before the `focus` event. When we
`e.preventDefault()` in this listener, the `focus` event will not fire.

This also means that the focus is not lost on the actual `input`
component which in turn means that we can maintain the selection /
cursor position inside the `input`.

We still use the `refocusInput()` as a fallback in case something else
goes wrong.

* add comments to describe _why_ we use `mousedown`

* ensure we handle mouse buttons correctly

* ensure we handle `Enter` and `Space` explicitly

Now that we use the `mousedown` event instead of the `click` event, we
have to make sure that we handle the `enter` and `space` keys
explicitly.

This used to be covered by the `click` event, but not for the `mousedown` event.

* ensure we focus the first element when using `ArrowDown` on the `ComboboxButton`

We go to the last one on `ArrownUp`, but we forgot to do this on
`ArrowDown`.

* fix tiny typo

Not related to this PR, but noticed it and fixed it anyway.

* update changelog

* ensure we reset the `isTyping` flag

While we are typing, the flag can remain true. But once we stop typing,
the `nextFrame` handler will kick in and set it to `false` again.

It currently behaves as a debounce-like function such that the
`nextFrame` callbacks are cancelled once a new event is fired.

* ensure unique callbacks in the `_disposables` array

This allows us to keep re-adding dispose functions and only register the
callbacks once.

Ideally we can use a `Set`, but we also want to remove a single callback
if the callback is disposed on its own instead of disposing the whole
group. For this we do require an `idx` which is not available in a
`Set` unless you are looping over all disposable functions.

* Update packages/@headlessui-react/src/components/combobox/combobox.tsx

Co-authored-by: Jonathan Reinink <jonathan@reinink.ca>

* Update packages/@headlessui-react/src/components/combobox/combobox.tsx

Co-authored-by: Jonathan Reinink <jonathan@reinink.ca>

* update comments

* abstract confusing logic to a `useFrameDebounce()` hook

* use correct path import

* add some breathing room

---------

Co-authored-by: Jonathan Reinink <jonathan@reinink.ca>
2024-04-03 15:06:41 +02:00
2024-03-12 15:33:00 +01:00
2020-09-16 18:19:33 +02:00
2022-01-31 12:29:27 +01:00
2020-09-16 18:19:33 +02:00
2023-01-01 06:25:25 -05:00

Headless UI

A set of completely unstyled, fully accessible UI components, designed to integrate beautifully with Tailwind CSS.


Documentation

For full documentation, visit headlessui.com.

Installing the latest version

You can install the latest version by using:

  • npm install @headlessui/react@latest
  • npm install @headlessui/vue@latest

Installing the insiders version

You can install the insiders version (which points to whatever the latest commit on the main branch is) by using:

  • npm install @headlessui/react@insiders
  • npm install @headlessui/vue@insiders

Note: The insiders build doesn't follow semver and therefore doesn't guarantee that the APIs will be the same once they are released.

Packages

Name Version Downloads
@headlessui/react npm version npm downloads
@headlessui/vue npm version npm downloads
@headlessui/tailwindcss npm version npm downloads

Community

For help, discussion about best practices, or any other conversation that would benefit from being searchable:

Discuss Headless UI on GitHub

For casual chit-chat with others using the library:

Join the Tailwind CSS Discord Server

Contributing

If you're interested in contributing to Headless UI, please read our contributing docs before submitting a pull request.

S
Description
Completely unstyled, fully accessible UI components, designed to integrate beautifully with Tailwind CSS.
Readme 6.5 MiB
Languages
TypeScript 95.3%
Vue 4.3%
JavaScript 0.3%
Shell 0.1%