Commit Graph

419 Commits

Author SHA1 Message Date
Robin Malfait 1739edb479 Calculate aria-expanded purely based on the open/closed state (#2610)
* define `aria-expanded` based on open/closed state

You shouldn't be able to open a Listbox/Menu/Combobox/... when the
component is in a disabled state, however if you open it, and then
disable it then it is still in an open state. Therefore the
`aria-expanded` should still be present.

This is also how other libraries behave.

It is also how the native `<select>` behaves. You can open it, disable
it programmatically and then you are still able to make a selection.

This seems enough evidence that this change is an improvement without
being a breaking change.

Fixes: #2602

* update changelog
2023-07-24 12:51:21 +02:00
Tim Robertson 076b03cf49 Skip updating state if sentinel has been unmounted (#2585)
* Skip updating state if sentinel has been unmounted

* use existing `useIsMounted` hook

* reformat code paths

---------

Co-authored-by: Robin Malfait <malfait.robin@gmail.com>
2023-07-10 10:42:31 +02:00
Robin Malfait 00fdb7e3cd Ensure IME works on Android devices (#2580)
* simplify `isComposing`

We had an issue #2409 where typing using an IME (Input Method Editor,
E.g.: Japanese — Romaji) already submitted characters while the user was
still composing the characters together.

1. Type `wa`
2. Expected result: `わ`
3. Actual result: `wあ` (where `あ` is the character `a`)

This was solved by not triggering change events at all until the
`compositionend` event was triggered. This worked fine for this use
case. However this also meant that only at the end of your typing
session (when you press `enter`/`space`) the actual value was submitted.

Fast forward to today, we received a new issue #2575 where this
behaviour completely broke on Android devices. Android _always_ use the
IME APIs for handling input... if we think about our solution form
above, it also means that while you are typing on an Android device no
options are being filtered at all. The moment you hit enter/space the
combobox will open and results will be filtered.

This is where this fix comes in. The goals are simple:

1. Make it work
2. Try to make the current code simpler

I started digging to see _why_ this `wあ` was even submitted. A normal
input field doesn't do that?! We have some code that does the following
things:

1. Sync the selected value with the `input` such that if you update the
   value from the outside, then the value in the `input` is up-to-date
   with the `displayValue` of that incoming value.
2. A fix for macOS VoiceOver to improve the VoiceOver experience when
   opening the `Combobox` component. This is done by manually resetting
   the value of the `input` field.

   1. Keep track of the current value
   2. Keep track of the current selection range (start/end) state
   3. Reset the input to an empty string `''`
   4. Restore the value to the captured value
   5. Restore the selection range

When you are typing, the input field doesn't have to update yet because
typing doesn't cause an option to become the `selected` option,
therefore it doesn't have to sync the value yet. So (1.) isn't the issue
here.

However, when you start typing, the Combobox should open and then we
trigger the macOS VoiceOver fix. This is touching the `input` field
because we change the value & selection.

Because we touched the `input` while the user was still in a composing
mode, it bailed and submitted whatever characters it had. This is the
part that we don't want. Not applying the macOS VoiceOver fix while
typing solves this issue. In addition, because _we_ are touching the
input field, VoiceOver is acting normally.

In hindsight, the solution is very simple: do not touch the input field
when the user is typing.

We still keep track whether the user `isComposing` so that we can bail
on the default `Enter` behaviour (marking the current option as the
selected option) because pressing `Enter` while composing should get out
of the IME.

Fixes: #2575

* update changelog
2023-07-06 14:35:35 +02:00
Robin Malfait a9e85634a9 Improve "outside click" behaviour in combination with 3rd party libraries (#2572)
* listen for both `mousedown` and `pointerdown` events

This is necessary for calculating the target where the focus will
eventually move to. Some other libraries will use an
`event.preventDefault()` and if we are not listening for all "down"
events then we might not capture the necessary target.

We already tried to ensure this was always captured by using the
`capture` phase of the event but that's not enough.

This change won't be enough on its own, but this will improve the
experience with certain 3rd party libraries already.

* refactor one-liners

* listen for `touchend` event to improve "outside click" on mobile devices

* update changelog
2023-07-03 16:21:03 +02:00
Robin Malfait 04fc6cfa06 Ensure the caret is in a consistent position when syncing the Combobox.Input value (#2568)
* ensure the caret is at the end of the input, after syncing the value

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.

* update changelog

* add selection guards

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.

* add tests
2023-06-30 12:58:44 +02:00
Jordan Pittman 0a9276d205 Ignore disconnected elements for outside clicks (#2544) 2023-06-19 16:02:38 -04:00
Robin Malfait a1d7c69b69 1.7.15 - @headlessui/react 2023-06-01 12:40:00 +02:00
Robin Malfait 8adaeeda45 Ensure moving focus within a Portal component, does not close the Popover component (#2492)
* abstract resolving root containers to hook

This way we can reuse it in other components when needed.

* allow registering a `Portal` component to a parent

This allows us to find all the `Portal` components that are nested in a
given component without manually adding refs to every `Portal` component
itself.

This will come in handy in the `Popover` component where we will allow
focus in the child `Portal` components otherwise a focus outside of the
`Popover` will close the it. In other components we often crawl the DOM
directly using `[data-headlessui-portal]` data attributes, however this
will fetch _all_ the `Portal` components, not the ones that started in
the current component.

* allow focus in portalled containers

The `Popover` component will close by default if focus is moved outside
of it. However, if you use a `Portal` comopnent inside the
`Popover.Panel` then from a DOM perspective you are moving the focus
outside of the `Popover.Panel`. This prevents the closing, and allows
the focus into the `Portal`.

It currently only allows for `Portal` components that originated from
the `Popover` component. This means that if you open a `Dialog`
component from within the `Popover` component, the `Dialog` already
renders a `Portal` but since this is part of the `Dialog` and not the
`Popover` it will close the `Popover` when focus is moved to the
`Dialog` component.

* ensure `useNestedPortals` register/unregister with the parent

This ensures that if you have a structure like this:

```jsx
<Dialog> {/* Renders a portal internally */}
   <Popover>
      <Portal> {/* First level */}
         <Popover.Panel>
            <Menu>
               <Portal> {/* Second level */}
                  <Menu.Items>
                  {/* ... */}
                  </Menu.Items>
               </Portal>
            </Menu>
         </Popover.Panel>
      </Portal>
   </Popover>
</Dialog>
```

That working with the `Menu` doesn't close the `Popover` or the `Dialog`.

* cleanup `useRootContainers` hook

This will allow you to pass in portal elements as well. + cleanup of
the resolving of all DOM nodes.

* handle nested portals in `Dialog` component

* expose `contains` function from `useRootContainers`

Shorthand to check if any of the root containers contains the given
element.

* add tests to verify that actions in `Portal` components won't close the `Popover`

* update changelog

* re-order use-outside-click logic

To make it similar between React & Vue

* inject the `PortalWrapper` context in the correct spot

* ensure to forward the incoming `attrs`
2023-05-19 15:37:01 +02:00
Jordan Pittman 9dff5456fa Handle clicks inside iframes (#2485)
* Handle clicks inside iframes

* Update changelog
2023-05-08 11:51:40 -04:00
Robin Malfait 67f3c4d824 Improve control over Menu and Listbox options while searching (#2471)
* add `get-text-value` helper

* use `getTextValue` in `Listbox` component

* use `getTextValue` in `Menu` component

* update changelog

* ensure we handle multiple values for `aria-labelledby`

* hoist regex

* drop child nodes instead of replacing its innerText

This makes it a bit slower but also more correct. We can use a cache on
another level to ensure that we are not creating useless work.

* add `useTextValue` to improve performance of `getTextValue`

This will add a cache and only if the `innerText` changes, only then
will we calculate the new text value.

* use better `useTextValue` hook
2023-05-04 14:41:44 +02:00
Mateusz Burzyński 0505e92b83 Move types condition to the front (#2469)
* move `types` condition to the front

* Update changelog

---------

Co-authored-by: Jordan Pittman <jordan@cryptica.me>
2023-05-01 12:21:28 -04:00
Jordan Pittman 7c0cbbbca7 Stop <Transition appear> from overwriting classes on re-render (#2457)
* Add raw layout support to Vue playground

We can’t use ?raw here because Vite uses that itself for stuff. So here we opt for ?layout=raw instead

* Fix Transition for `appear` overwriting classes on re-render

* Set initial state just before animating

* Remove unused import

* Refactor

* Capture snapshot of element just after first render

With the new `setInitial` call before the animation starts — we don’t see the actual initial render result in this test because the queue has been emptied by the time it ends

* Update changelog
2023-04-28 13:06:39 -04:00
Muhammad Ilham Mubarak 4c102946fe refactor Portal to use useOnUnmount hook (#2458) 2023-04-27 12:44:22 +02:00
Robin Malfait 74c987351f ensure cb in useOnUnmount is a stable reference 2023-04-26 14:56:06 +02:00
Muhammad Ilham Mubarak 5cfbb4b5e5 Ensure FocusTrap is only active when the given enabled value is true (#2456)
* fix(tabs): wrong tab focus when Tab contains a Dialog

* refactor(focus-trap): rename variable and move logic

* test(tabs): improve test by asserting the active element

* ensure `FocusTrap` is not active when `enabled = false`

* fix: move the enabled check to unmounting

* refactor to `useOnUnmount` hook

This will allow us to make the code relatively similar between React and
Vue.

* update changelog

---------

Co-authored-by: Robin Malfait <malfait.robin@gmail.com>
2023-04-26 14:51:01 +02:00
Robin Malfait 08127dd2ad [internal] add demo mode to Menu and Popover components (#2448)
* add demo mode to `Menu` and `Popover`

* update changelog
2023-04-21 13:51:26 +02:00
Jordan Pittman b98e642a67 Correctly handle IME composition in <Combobox.Input> (#2426)
* Don’t try to open combobox when composing characters

* wip

* Delay IME composition end until after keydown events

* Use `d.nextFrame` to handle `compositionend` event

* Update changelog
2023-04-17 10:17:28 -04:00
Robin Malfait c5d2e3b053 1.7.14 - @headlessui/react 2023-04-12 19:05:04 +02:00
Jordan Pittman 7ec06528d9 Don't scroll lock when transition isn't showing (#2422)
* Add tests

* Make transition initial state based on computed `show` prop

* Update changelog
2023-04-10 10:29:33 -04:00
Jordan Pittman 2063132f1a Merge className correctly when it’s a function (#2412)
* Add className tests for `render`

Fix snapshots

* Merge `className` correctly when it’s a function

* Update changelog
2023-04-03 14:43:09 -04:00
Robin Malfait c92a84782f Improve Combobox types to improve false positives (#2411)
* swap `Combobox` type order

If you use the default `Combobox` component then it defaults to
`Fragment`. This also means that if you provide an additional prop that
it would be forwarded to the `Fragment` but that won't work.

You do get a runtime error, but the types aren't 100% clear on what's
going on. In fact, they make it very confusing because it will use the
last "fallback" in all the `Combobox` definitions which marks the value
as "multiple".

Concretely, this means:
```ts
let [value, setValue] = useState('Tom Cook')

<Combobox
  value={value}
  onChange={setValue}
  placeholder="Hello!"
/>
```

Starts complaining about the `value` and `onChange` not handling the
`multiple` case correctly. But it should complain about the `placeholder`.

Switching the order _does_ solve this, but it is not the cleanest
solution.

Maybe we should be explicit about the `Fragment` case somehow.

However, there is a use case where I don't think TypeScript will be able
to help and it's a bit unfortunate.

```ts
let [value, setValue] = useState('Tom Cook')

<Combobox value={value} onChange={setValue} placeholder="Hello!">
   <div>
      {/* ... */}
   </div>
</Combobox>
```

This is valid because at runtime we will forward all the props to the
`div`. So not 100% sure what we should do here instead.

* update changelog
2023-04-03 17:46:20 +02:00
Jordan Pittman f4e9710bca Fix className hydration for <Transition appear> (#2390)
* Fix `className` hydration for `<Transition appear>`

* Update changelog
2023-03-22 11:41:09 -04:00
Kairui Liu d0888b03b5 Add FocusTrap event listeners once document has loaded (#2389)
* feat: addEventListener on document loaded

* Refactor

* Fix import

* Update changelog

* use function instead of arrow function

* make callback in `onDocumentReady` mandatory

---------

Co-authored-by: lkr <lkr@bytedance.com>
Co-authored-by: Jordan Pittman <jordan@cryptica.me>
Co-authored-by: Robin Malfait <malfait.robin@gmail.com>
2023-03-22 13:37:07 +01:00
Mathieu TUDISCO d55c77e655 [vue] Fix Combobox input disabled state (#2375)
* [vue] Fix Combobox input disabled state

* Add tests for disabled input in React and Vue

* Update changelog

---------

Co-authored-by: Jordan Pittman <jordan@cryptica.me>
2023-03-16 19:15:22 -04:00
Robin Malfait fc9a625414 Fix "Can't perform a React state update on an unmounted component." when using the Transition component (#2374)
* only change flags when mounted

* update changelog
2023-03-16 16:30:58 +01:00
Arber Sylejmani fb612f7580 Add form prop to form-like components such as RadioGroup, Switch, Listbox, and Combobox (#2356)
* Adds form prop to Switch component

* add `form` prop to `Switch` component in Vue

+ tests for both React and Vue

* add `form` prop to `Combobox` component

* add `form` prop to `Listbox` comopnent

* add `form` prop to `RadioGroup` component

* update changelog

* add Oxford comma

* cleanup `screen` import

---------

Co-authored-by: Robin Malfait <malfait.robin@gmail.com>
2023-03-14 13:36:49 +01:00
Robin Malfait 0c0601f87a Fix focus styles showing up when using the mouse (#2347)
* update playground examples to use a shared `Button`

* expose a `ui-focus-visible` variant

* keep track of a `data-headlessui-focus-visible` attribute

* do not set the `tabindex`

The focus was always set, but the ring wasn't showing up. This was also
focusing a ring when the browser decided not the add one.

Let's make the browser decide when to show this or not.

* update changelog
2023-03-10 22:00:35 +01:00
Robin Malfait df61edcf3e 1.7.13 - @headlessui/react 2023-03-03 21:09:06 +01:00
Robin Malfait 7e150e408c Fix restore focus to buttons in Safari, when Dialog component closes (#2326)
* update dialog playground example

Includes a generic `Button` component that has explicit focus styles.

* keep track of "focus" history

Safari doesn't "focus" buttons when you mousedown on them. This means
that we don't capture the correct element to restore focus to when
closing a `Dialog` for example.

Now, we will make sure to keep track of a list of last "focused" items.
We do this by also capturing elements when you "click", "mousedown" or
"focus".

* let's use a button instead of a div in tests

* make `target` for Vue consistent with React

* update changelog
2023-03-03 18:24:57 +01:00
Robin Malfait c759016fa3 Fix invalid warning when using multiple Popover.Button components inside a Popover.Panel (#2333)
* add a bunch of tests to ensure we won't regress on this again

* fix incorrect warning when using multiple `Popover.Button` inside `Popover.Panel`

* update changelog
2023-03-03 14:59:10 +01:00
Robin Malfait 989cd6b040 Fix XYZPropsWeControl and cleanup internal TypeScript types (#2329)
* cleanup `XYZPropsWeControl`

The idea behind the `PropsWeControl` is that we can omit all the fields
that we are controlling entirely. In this case, passing a prop like
`role`, but if we already set the role ourselves then the prop won't do
anything at all. This is why we want to alert the end user that it is an
"error".

It can also happen that we "control" the value by default, but keep
incoming props into account. For example we generate a unique ID for
most components, but you can provide your own to override it. In this
case we _don't_ want to include the ID in the `XYZPropsWeControl`.

Additionally, we introduced some functionality months ago where we call
event callbacks (`onClick`, ...) from the incoming props before our own
callbacks. This means that by definition all `onXYZ` callbacks can be
provided.

* improve defining types

Whenever we explicitly provide custom types for certain props, then we
make sure to omit those keys first from the original props (of let's say
an `input`). This is important so that TypeScript doesn't try to "merge"
those types together.

* cleanup: move `useEffect`

* add `defaultValue` explicitly

* ensure tests are not using `any` because of `onChange={console.log}`

The `console.log` is typed as `(...args: any[]) => void` which means
that it will incorrectly mark its incoming data as `any` as well.
Converting it to `x => console.log(x)` makes TypeScript happy. Or in
this case, angry since it found a bug.

This is required because it _can_ be that your value (e.g.: the value of
a Combobox) is an object (e.g.: a `User`), but it is also nullable.

Therefore we can provide the value `null`. This would mean that
eventually this resolves to `keyof null` which is `never`, but we just
want a string in this case.

```diff
-export type ByComparator<T> = (keyof T & string) | ((a: T, b: T) => boolean)
+export type ByComparator<T> =
+  | (T extends null ? string : keyof T & string)
+  | ((a: T, b: T) => boolean)
```

* improve the internal types of the `Combobox` component

* improve the internal types of the `Disclosure` component

* improve the internal types of the `Listbox` component

* improve the internal types of the `Menu` component

* improve the internal types of the `Popover` component

* improve the internal types of the `Tabs` component

* improve the internal types of the `Transition` component

* use `Override` in `Hidden` as well

* cleanup unused code

* don't check the `useSyncExternalStoreShimClient`

* don't check the `useSyncExternalStoreShimServer`

* improve types in the render tests

* fix `Ref<TTag>` to be `Ref<HTMLElement>`

* improve internal types of the `Transition` component (Vue)

+ add `attrs.class` as well

* use different type for `AnyComponent`

* update changelog
2023-03-02 22:50:41 +01:00
Robin Malfait 948ae73608 Allow root containers from the Dialog component in the FocusTrap component (#2322)
* add (failing) test to verify moving focus to 3rd party containers work

* pass `resolveRootContainers` to `FocusTrap`

* handle lazy containers in `FocusTrap`

* update changelog
2023-03-01 18:13:07 +01:00
Dilshod de7ddf9e45 Enable native label behavior for Switch component (#2265)
* add native label behavior for switch

* Add reference tests for React and Vue

These don’t work in JSDOM so they’re skipped but we can use these to reference expected behavior once we have playwright-based tests

* Fix Vue playground switch example

* Only prevent default when the element is a label

* Port change to Vue

* Update changelog

---------

Co-authored-by: Jordan Pittman <jordan@cryptica.me>
2023-02-28 12:22:37 -05:00
Robin Malfait 213dd529bf Ensure Transition component completes if nothing is transitioning (#2318)
* make `disposables` consistent

Also added a `group` function, this allows us to spawn a _sub_
disposables group that can be disposed on its own, but will also be
disposed the moment the "parent" is disposed.

* ensure Transition component works when nothing is transitioning

* update changelog
2023-02-28 12:38:11 +01:00
Robin Malfait 885f446e4e 1.7.12 - @headlessui/react 2023-02-24 16:29:14 +01:00
Robin Malfait 9ecd8dd926 Fix Dialog cleanup when the Dialog becomes hidden (#2303)
* use the Dialog's parent as the root for the Intersection observer

We have some code that allows us to auto-close the dialog the moment it
gets hidden. This is useful if you use a dialog for a mobile menu and
you resizet he browser. If you wrap the dialog in a `md:hidden` then it
auto closes. If we don't do this, then the dialog is still locking the
scrolling, keeping the focus in the dialog, ... but it is not visible.

To solve this we use an `IntersectionObserver` to verify that the
`boundingClientRect` is "gone" (x = 0, y = 0, width = 0 and height = 0).

However, the intersection observer is not always triggered. This happens
if the main content is scrollable.

Setting the `root` of the `IntersectionObserver` to the parent of the
`Dialog` does seem to solve it.

Not 100% sure what causes this behaviour exactly.

* use a `ResizeObserver` instead of `IntersectionObserver`

* implement a `ResizeObserver` for the tests

* update changelog
2023-02-24 13:22:29 +01:00
Robin Malfait d1ca3a9797 fix false positive log when running tests
Let's wrap the test in `act` to get rid of the warning. In practice
(while testing in the browser) the actual warning doesn't seem to affect
the user experience at all.

The `act` function is typed in a strange way (`Promise<undefined> &
void`). Yet the actual contents of the `act` callback is returned as
expected. Therefore we overrode the type of `act` to make sure this
reflects reality better. (Thanks @thecrypticace!)

Also added an additional check to make sure the actual `container` is
available to extra ensure we are not lying by overriding the type.
2023-02-21 13:36:31 +01:00
Robin Malfait 569cec7514 Fix change event incorrectly getting called on blur (#2296)
* drop `d.enqueue` & `d.workQueue`

This was only used in tests and doesn't seem to be necessary.

* drop `handleChange` from the `ComboboxInput` component

This only emitted a `change` event, which Vue already emits as well.

* drop `onChange` from incoming props

This is an odd one. In Chrome this means that the `@change` is still
being called, but if we keep it, then the `@change` is _also_ called on
blur resulting in odd bugs.

Droping it fixes that issue.

That said, the `@change` is _still_ emitted and therefore the callback
is properly called and the `ComboboxInput` still can interact with the
`@change` event.

* update changelog
2023-02-21 12:19:35 +01:00
Jordan Pittman b8c214eebb Make React types more compatible with other libraries (#2282)
* Export explicit props types

* wip

* wip

* wip

* wip dialog types

* wip

* Fix build

* Upgrade esbuild

* Add aliased types for ComponentLabel and ComponentDescription

* Update lockfile

* Update changelog

* Update exported prop type names

* Make onChange optional

* Update tests

* Use `never` in CleanProps

Using a branded type doesn’t work properly with unions

* Fix types

* wip

* work on types

* wip

* wip

* Tweak types in render helpers

* Fix CS

* Fix changelog

* Tweak render prop types for combobox

* Update hidden props type name

* remove unused type

* Tweak types

* Update TypeScript version
2023-02-20 12:26:17 -05:00
Robin Malfait c7f6bc60ed Fix nested Popover components not opening (#2293)
* fix nested `Popover`s not working

* update changelog
2023-02-17 23:05:14 +01:00
Robin Malfait 10efaa921d Ensure the main tree and parent Dialog components are marked as inert (#2290)
* drop `@ts-expect-error`, because `inert` is available now

* fix logical error

We want to apply `inert` when we _don't_ have nested dialogs, because if
we _do_ have nested dialogs, then the inert should be applied from the
nested dialog (or visually the top most dialog).

* update changelog

* replace `useInertOthers` with `useInert`

* add `assertInert` and `assertNotInert` accessibility assertion helpers

* ensure the `main tree` root is marked as inert

As well as the parent dialogs in case of nested dialogs.
2023-02-17 16:49:41 +01:00
Robin Malfait 619d103114 update CHANGELOG 2023-02-15 15:33:02 +01:00
Robin Malfait 2c2a22bd4f 1.7.11 - @headlessui/react 2023-02-15 15:10:39 +01:00
Norman Dilthey 399ab4e22c change test to test whether the underlying dom tag is changed to span when using as prop (#2283)
Test in line 105 already covers using the as tag to change the underlying dom tag to an anchor tag. Therefore we can test whether a span tag is correctly rendered for example.
2023-02-15 12:17:28 +01:00
Robin Malfait adfe121678 Start cleanup phase of the Dialog component when going into the Closing state (#2264)
* introduce `opening` and `closing` states

Also represent them as bits so that we can easily combine them while we
are transitioning from one state to the other.

* update `open/closed` state checks

Instead of checking whether it is in one state or an other, we can check
if the current state contains some potential sub-state.

This allows us to still check if we are in the `Open` state, while also
`Closing` because the state will be `S.Open | S.Closing`.

* expose `flags` from the `useFlags` hook

* add the `Closing` and `Opening` states to the Open/Closed state

* create dedicated `abcEnabled` variables

* keep the `State.Closing` into account for `scroll locking` and `inert others`

* add a test for the `Closing` state impacting the `Dialog` component

* cleanup unused imports

* add `unmount` util to the Vue Test renderer

* update changelog
2023-02-15 12:14:03 +01:00
Robin Malfait 22e388eb8d update changelog 2023-02-13 13:07:39 +01:00
Thet Naing Tun db58664992 refactor: use proper type for switch forward ref (#2277) 2023-02-13 13:06:44 +01:00
Robin Malfait fcfd554514 Ensure we reset the activeOptionIndex if the active option is unmounted (#2274)
* ensure we reset the `activeOptionIndex` if the active option is unmounted

Unmounting of the active option can happen when you are in a
multi-select Combobox, and you filter out all the selected values. This
means that the moment you press "Enter" on an active item, it becomes
the selected item and therefore will be filtered out.

* update changelog
2023-02-10 19:54:58 +01:00
Robin Malfait b9af614919 Re-focus Combobox.Input when a Combobox.Option is selected (#2272)
* re-focus `Combobox.Input` when a `Combobox.Option` is selected

Except on mobile devices (ideally devices using a virtual keyboard), so
that the virtual keyboard won't be triggered every single time we
re-focus that input field.

* update changelog
2023-02-10 16:30:53 +01:00
Robin Malfait 7ecf8323dc Move aria-multiselectable to [role=listbox] in the Combobox component (#2271)
* move `aria-multiselectable` to `[role=listbox]` in the `Combobox` component

* update changelog
2023-02-10 15:41:30 +01:00