899 Commits

Author SHA1 Message Date
Jordan Pittman 08baf094d2 Update changelog 2024-02-07 17:12:43 -05:00
Jonathan Reinink 4156c45f78 Fix Combobox activeOption render prop (#2973)
* Fix Combobox `activeOption` render prop

* Update changelog
2024-02-07 17:09:42 -05:00
Jordan Pittman 25ba013ba1 Tweak wording in changelog 2024-02-06 16:16:44 -05:00
Jordan Pittman 08d380aed1 Update changelog 2024-02-06 16:16:01 -05:00
Jordan Pittman c71c6763f1 Make Listbox submit form on Enter when not open (#2972) 2024-02-06 16:06:35 -05:00
Jordan Pittman 680db08b00 Remove outdated esbuild deps 2024-02-06 15:04:02 -05:00
Robin Malfait 0e0277a684 Allow setting custom tabIndex on the <Switch /> component (#2966)
* allow setting a custom `tabIndex` on the `<Switch />` component

* update changelog
2024-02-03 17:31:02 +01:00
Robin Malfait da94b80860 Attempt form submission when pressing Enter on Checkbox component (#2962)
* attempt to submit form when pressing `Enter` on the `Checkbox` component

* add test to verify form submissions when pressing enter works

* update changelog
2024-02-02 15:51:58 +01:00
Robin Malfait edbcb81ead Add hidden attribute to internal <Hidden /> component when the Features.Hidden feature is used (#2955)
* add `hidden` attribute for `<Hidden features={Features.Hidden}>`

* update changelog
2024-01-31 13:29:50 +01:00
Robin Malfait ce17c6d15f Ensure children prop of Field component can be a render prop (#2941)
* ensure `children` prop can be a render prop

* update changelog
2024-01-23 14:01:05 +01:00
Robin Malfait f2bc6fdd40 Use isFocused instead of isFocusVisible for Input and Textarea components (#2940)
* use `isFocused` in `Input` and `Textarea`

We do this because we always want to show the focus ring regardless of
whether you used the mouse or the keyboard.

* update changelog
2024-01-23 12:13:55 +01:00
Jordan Pittman 3b2a102e8d Don’t override explicit disabled prop for components inside <MenuItem> (#2929)
* Don’t override explicit disabled prop inside `<MenuItem>`

* Update changelog
2024-01-16 15:34:41 -05:00
Robin Malfait aff438eb06 Prevent default behaviour when clicking outside of a Dialog.Panel (#2919)
* use `event.preventDefault()` in the `useOutsideClick` on Dialog's

When using a `Dialog`, we should prevent the default behaviour of the
event that triggered the "close" in the `useOutsideClick` call.

We recently made improvements to improve outside click behaviour on
touch devices (https://github.com/tailwindlabs/headlessui/pull/2572) but
due to the `touchend` event, the touch is still forwarded and therefore
a potential button _behind_ the "backdrop" will also be clicked. This is
not what we want.

Added the `event.preventDefault()` for the Dialog specifically because
there are other places where we use `useOutsideClick` and where we _do_
want the behaviour where the click just continues. A concrete example of
this is 2 `Menu`'s next to eachother where you open the first one, and
then click on the second one. This should close first one (outside
click) and open the second one (by not preventing the event)

* update changelog
2024-01-09 20:06:55 +01:00
Robin Malfait 2b7a57e337 Expose disabled state on <Tab /> component (#2918)
* expose `disabled` on `<Tab/>` component

This will expose it such that you can use it with `ui-disabled`. In the
Alpha version of React, you can also use `data-[disabled]` because it
will be exposed as `data-disabled` over there as well.

Fixes: #2864

* update changelog
2024-01-09 15:45:30 +01:00
Robin Malfait b83b5b6ffc sync CHANGELOG 2024-01-08 16:14:28 +01:00
Robin Malfait f6a99cad26 update changelog 2024-01-06 02:05:13 +01:00
Robin Malfait 799e98a56e improve iOS scroll locking
The scroll locking on iOS was flickering in some scenario's due to the
`window.scrollTo(0, 0)` related code. Instead of that, we now cancel
touch moves instead but still allow it in scrollable containers inside
the Dialog itself.

This was already applied in the React version, but this adds the same
improvement to the Vue version as well.
2024-01-06 01:58:22 +01:00
Robin Malfait bc4a744947 fix incorrect activeIndex when handling Focus.Previous
This is already available in the React version, now let's sync it in the
Vue version as well.
2024-01-06 01:51:07 +01:00
Robin Malfait a3276570d2 sync package-lock.json 2024-01-05 12:54:54 +01:00
Robin Malfait 33286d0c80 2.0.0-alpha.4 — @headlessui/react 2024-01-03 15:06:09 +01:00
Robin Malfait a73007388f Ensure playgrounds work + switch to npm workspaces (#2907)
* bump Next in playground

* convert legacy Link after Next.js bump

* update yarn.lock

* switch to npm workspaces

* move `packages/playground-*` to `playgrounds/*`

* use `npm` instead of `yarn`

* sync package-lock.json

* use node 20 for insiders releases
2024-01-03 14:26:12 +01:00
Robin Malfait 3b961a690f Ensure Input, Select and Textarea expose Ref related types (#2902)
* ensure `Input`, `Select` and `Textarea` expose `Ref` related types

* update changelog
2023-12-27 20:34:32 +01:00
Robin Malfait 8c882e047a Make playgrounds build again (#2894)
* sync yarn.lock

* drop resolutions from root package.json

This is done in the `package.json` from the `playground-react` package

* update next.config.js

Use `buildActivity` instead of `autoPrerender`

* ignore type checking in playground files

This is not ideal, but it is the first step in making the build pass
again.
2023-12-21 16:02:35 +01:00
Robin Malfait 847976a310 fix typo 2023-12-21 02:55:46 +01:00
Robin Malfait d94038f198 2.0.0-alpha.3 — @headlessui/react 2023-12-21 02:51:25 +01:00
Robin Malfait 20b3b65e76 Further fine tune scroll locking on iOS (#2891)
* further fine tune scroll locking on iOS

* update CHANGELOG
2023-12-21 02:49:06 +01:00
Robin Malfait 5976b9a624 map alpha versions to the next channel/tag 2023-12-21 00:46:31 +01:00
Robin Malfait 13f4cd5a7f 2.0.0-alpha.2 — @headlessui/react 2023-12-21 00:32:50 +01:00
Robin Malfait 33a5893e4f Improve cancellation of events when using disabled or aria-disabled attributes (#2890)
* only cancel certain events when disabled

The initial idea was that whenever an element had the `disabled` or
`aria-disabled` prop/attribute that we were going to remove all the
event listeners.

However, this is not ideal because in some scenario's we were actually
explicitly adding `onClick()` listeners (for `<a>` elements) to
`e.preventDefault()` when the link was marked as "disabled" to prevent
it executing the actual link click.

This commit will allow all defined listeners as-is, however, if you are
using one of the following event listeners:

- `onClick`
- `onPointerUp`
- `onPointerDown`
- `onMouseUp`
- `onMouseDown`
- `onKeyUp`
- `onKeyPress`
- `onKeyDown`

Then we will replace it with `(e) => e.preventDefault()` instead.

This way we are still invoking your own listeners, but are explicitly
calling `e.preventDefault()` on listeners that should not be executed in
the first place when an element is `disabled`.

* update CHANGELOG.md

* update CHANGELOG.md
2023-12-21 00:09:08 +01:00
Robin Malfait 7a1940e0b2 allow horizontal scrolling when scroll locking (#2889) 2023-12-20 23:55:41 +01:00
Robin Malfait 9f0b19f41f 2.0.0-alpha.1 — @headlessui/react 2023-12-20 20:12:39 +01:00
Robin Malfait 9159326bea skip checking types for now
Not really an issue with the types, but with this part of the GitHub
Actions
2023-12-20 20:12:39 +01:00
Robin Malfait e662f12398 2.0.0 Alpha prep (#2887)
* bump React & React DOM dependencies

* fix typo `TOmitableProps` → `TOmittableProps`

* bump prettier

* run prettier after prettier version bump

* bump TypeScript

* run prettier after TypeScript version bump

* enable `verbatimModuleSyntax`

This ensures all imported types are using the `type` keyword.

* add `type` to type related imports

* add common testing scenarios

Will be used in the new and existing components.

* add script to make Next.js happy

Right now Next.js does barrel file optimization and re-writing imports
to a real path in the `dist` folder. Most of those rewrites don't
actually exist because they have an assumption:

```js
import { FooBar } from '@headlessui/react'
```

is rewritten as:
```js
import { FooBar } from '@headlessui/react/dist/components/foo-bar/foo-bar'
```

This script will make sure these paths exist...

* improve `by` prop, introduce `useByComparator`

This hook has a default implementation when comparing objects. If the
object contains an `id`, then we will compare the objects by their
`id`'s without the user of the library needing to specify `by="id"`.

If the objects don't have an `id` prop, then the default is still to
compare by reference (unless specicified otherwise).

* sync yarn.lock

* rename `Features` to `HiddenFeatures` for `Hidden` component

* rename `Features` to `FocusTrapFeatures` in `FocusTrap` component

* rename `Features` to `RenderFeatures` in `render` util

* add `floating-ui` as a dependency + introduce internal floating related components

* bump Vue dependencies

* ensure scroll bar calculations can't go negative

* improve types in `@headlessui/vue`

* use snapshot tests for `Transition` tests in `@headlessui/vue`

* use snapshot tests for `portal` tests in `@headlessui/vue`

* rename `src/components/transitions/` to `src/components/transition/` (singular)

This is so that we can be consistent with the other components.

* drop custom `toMatchFormattedCss`, prefer snapshot tests instead

* use snapshot tests for `Label` tests in `@headlessui/vue`

* use snapshot tests for `Description` tests in `@headlessui/vue`

* sort exported components in tests for `@headlessui/vue`

* use snapshot tests in `@headlessui/tailwindcss`

* rename `mergeProps` to `mergePropsAdvanced`

This is a more complex version of a soon to be exported `mergeProps`
that we will be using in our components.

* do not expose `aria-labelledby` if it is only referencing itself

* expose boolean state as `kebab-case` instead of `camelCase`

These are the ones being exposed inside `data-headlessui-state="..."`

* expose boolean data attributes

A slot with `{active,focus,hover}` will be exposed as:
```html
<span data-headlessui-state="active focus hover"></span>
```

But also as boolean attributes:
```html
<span data-active data-focus data-hover></span>
```

* improve internal types for `className` in `render` util

* ensure we keep exposed data attributes into account when trying to forward them to the component inside the `Fragment`

* add small typescript type fix

This is internal code, and the public API is not influenced by this
`:any`. It does make TypeScript happy.

* introduce `mergeProps` util to be used in our components

This will help us to merge props, when event handlers are available they
will be merged by wrapping them in a function such that both (or more)
event handlers are called for the same `event`.

* add new internal `Modal` component

* fix: when using `Focus.Previous` with `activeIndex = -1` should start at the end

* prefer `window.scrollY` instead of `window.pageYOffset`

Because `window.pageYOffset` is deprecated.

* add `'use client'` directives on client only components

These components use hooks that won't work in server components and you
will receive an error otherwise.

* drop `import 'client-only'` in favor of the `'use client'` directive

* add React Aria dependencies

* pin beta dependencies

* prettier bump formatting

* improve TypeScript types in tests

* use new Jest matchers instead of deprecated ones

* improve typescript types in Vue

* prefer `useLabelledBy` and `useDescribedBy`

* add internal `DisabledProvider`

* add internal `IdProvider`

* add internal `useDidElementMove` hook

* add internal `useElementSize` hook

* add internal `useIsTouchDevice` hook

* add internal `useActivePress` hook

* use snapshot tests for `Description` tests

* use snapshot tests for `Label` tests

* use snapshot tests for `Portal` tests

* use snapshot tests for `render` tests

* add (private) `Tooltip` component

Currently this one is not ready yet, so its not publicly exposed yet.

* add internal `FormFields` component

This one adds a component to render (hidden) inputs for native form
support. It also ensures that form fields can be hoisted to the end of
the nearest `Field`. If the components are not inside a `Field` they
will be rendered in place.

* add new `Button` component

* add new `Checkbox` component

* add new `DataInteractive` component

* add new `Field` component

* add new `Fieldset` component

* add new `Legend` component

* add new `Input` component

* add new `Select` component

* add new `Textarea` component

* export new components

* WIP

* remove `within: true`

This only makes sense if anything inside the current element receives
focus, which is not the case for `input`, `select`, `textarea` or
`Radio/RadioOption`.

* group focus/hover/active hooks together

* conditionally link anchor panel

* immediately focus the container

* prevent premature disabling of `Listbox`'s floating integration

+ Track whether the button moved or not when disabling such that we can
  disable the transitions earlier.

* improve scroll locking on iOS

* skip hydration tests for now

* skip certain focus trap tests for now

* update CHANGELOG.md

* add missing requires

* drop unused `@ts-expect-error`

* ignore type issues in playgrounds

These playgrounds are mainly test playgrounds. Lower priority for now,
we will get back to them.

* add yarn resolutions to solve swc bug
2023-12-20 19:57:57 +01:00
Jordan Pittman 01a34cb0c4 Update changelog 2023-12-12 15:14:49 -05:00
Евгений c24ba868bd Fix error when transition classes contain new lines (#2871)
* fix DOMException when remove class with '\n' character in react 'transition' component

* Split classes on all whitespace

* Revert "fix DOMException when remove class with '\n' character in react 'transition' component"

This reverts commit 76e835441b9cb84a1d867e1a37496c55cae86179.

* fix typo

* Add test

* Fix CS

* Update changelog

---------

Co-authored-by: Jordan Pittman <jordan@cryptica.me>
2023-12-12 15:09:55 -05:00
Jordan Pittman c25e2e6036 Fix CJS types (#2880)
* Fix Vue type error

* Add separate CTS types

* Add “Are The Types Wrong” CLI

* wip

* Bump node versions in workflows

* wip

* wip

* wip

* yolo

* yolo (again?)

* wip

* wip
2023-12-12 11:43:34 -05:00
Jordan Pittman c2096b0ddd Update changelog 2023-12-05 11:25:18 -05:00
Jordan Pittman 684623131b Fix outside click detection when component is mounted in the Shadow DOM in Vue 2023-12-05 11:22:33 -05:00
Jordan Pittman 7b30e06088 Fix outside click detection when component is mounted in the Shadow DOM (#2866)
* Fix outside click detection when component is mounted in the Shadow DOM

* Fix code style

* Fix error
2023-12-05 11:20:37 -05:00
Jordan Pittman 24486b39ca Fix example 2023-11-17 14:39:35 -05:00
Jordan Pittman d3c2a192bb Add Vue empty states example 2023-11-17 13:21:15 -05:00
Jordan Pittman 475db7c173 Make the empty state interactive 2023-11-17 13:00:25 -05:00
Jordan Pittman c2c43c390b Add virtualized empty state example 2023-11-17 13:00:25 -05:00
Robin Malfait bfacb648dc Fix VoiceOver bug for Listbox component in Chrome (#2824)
* fix VoiceOver bug for Listbox in Chrome

Chrome currently has a bug if you use a `Listbox` with a `Label` and use
the `aria-multiselectable` attribute. This combination will cause
VoiceOver to _not_ announce the `role="option"` elements when
interacting with them.

If we drop the `aria-multiselectable` OR the `aria-labelledby` it starts
working. Alternatively replacing `aria-labelledby` with `aria-label`
won't work either.

I filed a Chrome bug report about this here: https://bugs.chromium.org/p/chromium/issues/detail?id=1498261

---

Luckily there is a workaround in our `Listbox` implementation. Right now
we always require the `Listbox.Button` to be there. The
`Listbox.Options` component doesn't work on its own in our
implementation.

This means that whenever we open the `Listbox` that we have to go via
the `Listbox.Button`. This `Listbox.Button` is already labelled by the
`Listbox.Label` if there is one.

This also means that we can safely drop the `id` of the label inside the
`aria-labelledby` from the `Listbox.Options`.

This wouldn't have worked if our `Listbox.Options` could be used in a
standalone way without the `Listbox.Button`.

At the end of the day the hierarchy looks like this:

- Options is labelled by the Button
   - Button is labelled by the Label
      - Label

Fixes: #2817

* update changelog
2023-11-02 17:52:43 +01:00
Jordan Pittman 1469b85c36 Update changelog 2023-10-04 13:45:58 -04:00
Jordan Pittman 20a224aaa4 Fix state data attribute in Vue (#2787)
* Add tests

* Fix state data attribute in Vue
2023-10-04 13:39:26 -04:00
Robin Malfait 99cdf91631 Implement new virtual API for the Combobox component (#2779)
* add `(Vue)` or `(React)` to playground header

* show amount of items in virtualized example

* improve calculating the active index

* disable strict mode

* update virtualized playground examples with preferred API

* optimize `calculateActiveIndex`

* implement new `virtual` API

* update changelog
2023-10-02 11:55:20 +02:00
Nestor Vera d4a94cb564 Add missing variants to README.md (#2769) 2023-09-25 12:48:59 +02:00
Jordan Pittman 0f34486064 Make sure as={Fragment} doesn’t result in a render loop (#2760)
* Make sure `as={Fragment}` doesn’t result in a render loop

* Add comment about usage

* Fix render loop on popover panel too

* Update changelog
2023-09-20 08:57:27 -04:00
zakstucke 2a64c131bd Update Radio's OptionFn effect deps to fix infinite loop. (#2758) 2023-09-19 11:24:59 +02:00