* make combobox playgrounds in React and Vue similar
* syncing of the input should happen when the value changes internally or externally
I also got rid of the manually dispatching of the change event if the
value changes from internally.
I think the correct mental model is:
- That the `Combobox.Input` value should change if the selected value
changes from the outside or from the inside.
- Note: It should _not_ do that if you are currently typing (once you
choose a new value it will re-sync, once you reset (escape / outside
click) it will also sync again).
- The `onChange`/`onInput` of the `Combobox.Input` itself should only be
called if you as the user type something. Not when the value is
"synced" based on the selected value. We were currently manually
dispatching events which works (to a certain extend) but smelled a bit
fishy to me.
The manual dispatching of events tried to solve an issue
(https://github.com/tailwindlabs/headlessui/issues/1875), but I think
this can be solved in 2 other ways that make a bit more sense:
1. (Today) Use the `onBlur` on the input to reset the `query` value to filter
options.
2. (In the future) Use an exposed `onClose` (or similar) event to reset
your `query` value.
* update changelog
* ignore flakey test
* fix ref stealing
When a higher-level component (like `Transition`) provides a `ref` to
its child component, then it will override the `ref` that was
potentially already on the child.
This will make sure that these are merged together correctly.
Fixes: #985
* update changelog
* improve tracking of transitionableChildren
* remove weird outlier snapshots
If anything is still wrong the tests will still fail but the diffs will
be easier to read.
* remove event handling from `useTransition`
* handle before/after events in `Transition` directly
* fix incorrect logic bug in tests
* add very explicit test for transition event order
* ignore flakey tests for now
We will get back to these!
* ensure cancellation of transitions works properly
* update changelog
* cleanup README files
* ignore flakey tests for now
There are a handful of tests that are pretty flakey and fail every once
in a while on CI, I don't want to remove them yet, but rather ignore
them for now.
I am going to experiment with using Playwright/Puppeteer to use a real
browser instead.
* bump dev dependencies to React 18
* setup Jest to include `IS_REACT_ACT_ENVIRONMENT`
* prefer `useId` from React 18 if it exists
In React 16 & 17, where `useId` doesn't exist, we will fallback to our
implementation we have been using up until now.
The `useId` exposed by React 18, ensures stable references even in SSR
environments.
* update expected events
React 18 now uses the proper events:
- `blur` -> `focusout`
- `focus` -> `focusin`
* ensure to wait a bit longer
This is a bit unfortunate, but since React 18 now does an extra
unmount/remount in `StrictMode` to ensure that your code is
ConcurrentMode ready, it takes a bit longer to settle what the DOM sees.
That said, this is a temporary "hack". We are going to experiment with
using tools like Puppeteer/Playwright to run our tests in an actual
browser instead to eliminate all the weird details that we have to keep
in mind.
* prefer `.focus()` over `fireEvent.focus(el)`
* abstract `microTask` polyfill code
* prefer our `focus(el)` function over `el.focus()`
Internally we would still use `el.focus()`, but this allows us to have
more control over that `focus` function.
* add React 18 to the React Playground
* improve hooks for React 18
- Improving the cleanup of useEffect hooks
- useIsoMorphicEffect instead of normal useEffect, so that we can use
useLayoutEffect to be a bit quicker.
* improve disposables
- This allows us to add event listeners on a node, and get automatic
cleanup once `dispose` gets called.
- We also return all the `d.add` calls, so that we can cleanup specific
parts only instead of everything or nothing.
* reimplement the Transition component to be React 18 ready
* wait an additional frame for everything to settle
* update playground examples
* suppressConsoleLogs for RadioGroup components
* update changelog
* keep the `to` classes for a smoother transition
In the next transition we will remove _all_ classes provided and re-add
the once we need.
---
Some extra special thanks:
- Thanks @silvenon for your initial work on the `transition` events in #926
- Thanks @thecrypticace for doing late-night debugging sessions
Co-authored-by: =?UTF-8?q?Matija=20Marohni=C4=87?= <matija.marohnic@gmail.com>
Co-authored-by: Jordan Pittman <jordan@cryptica.me>
* use esbuild for React instead of tsdx
* remove tsdx from Vue
* use consistent names
* add jest and prettier
* update scripts
* ignore some folders for prettier
* run lint script instead of tsdx lint
* run prettier en-masse
This has a few changes because of the new prettier version.
* bump typescript to latest version
* make typescript happy
* cleanup playground package.json
* make esbuild a dev dependency
* make scripts consistent
* fix husky hooks
* add dedicated watch script
* add `yarn playground-react` and `yarn react-playground` (alias)
This will make sure to run a watcher for the actual @headlessui/react
package, and start a development server in the playground-react package.
* ignore formatting in the .next folder
* run prettier on playground-react package
* setup playground-vue
Still not 100% working, but getting there!
* add playground aliases in @headlessui/vue and @headlessui/react
This allows you to run `yarn react playground` or `yarn vue playground`
from the root.
* add `clean` script
* move examples folder in playground-vue to root
* ensure new lines for consistency in scripts
* fix typescript issue
* fix typescript issues in playgrounds
* make sure to run prettier on everything it can
* run prettier on all files
* improve error output
If you minify the code, then it could happen that the errors are a bit
obscure. This will hardcode the component name to improve errors.
* add the `prettier-plugin-tailwindcss` plugin, party!
* update changelog
* increase maximum error offset for CI tests
We try to detect how long durations took. However there is no nice way
to time this in JSDOM. Instead we take snapshots every
requestAnimationFrame and when things change we also write down the
time.
This solution is not ideal and results in false positives (especially on
CI environments).
However, it is good enough to ensure that the duration is not 0 and not
500.
* cleanup README's and link to docs site
* remove readme's in favor of doc site
This will be easier, so that we don't have to maintain multiple repo's.
* rename Transition to TransitionRoot
This will allow us to write it as:
- TransitionRoot
- TransitionChild
This has the added benefit that it doesn't collide with the internal
Transition component from Vue itself.
* alias Transition.Root to Transition
This allows us to write:
- Transition.Root
- Transition.Child
If you have a standalone Transition, then you can still use <Transition /> as is.
* drop unusued import
* update changelog
* add redent function when verifying snapshots
This allows us not to care about the correct amount of spaces and always
produces a clean output.
* make the container the parent of the wrapper element
* drop the visible prop on the Portal component
* drop visible prop on Portal component
+ Also cleanup a little bit
* expose the RenderStrategy
* implement Transition component in Vue
* expose Transition component
* add Transitions to the Dialog example
- Made the use of `const` and `let` consistent
- import required functions and types from 'react' instead of using the
`React.` namespace.
- Added `Expand` type, which can expand complex types to their "final"
result.
- Ensured that we use `as const` for DEFAULT_XXX_TAG where we used a
string. So that we have the type of `div` instead of `string` for
example.
- Used `interface` over `type` where possible. I'm personally more of a
`type` fan. But the TypeScript recommends `interfaces` where possible
because they are faster, yield better error messages and so on.
* add unmount strategy to README (React)
* add unmount strategy to README (Vue)
* add different render features (React)
* use render features in Menu and Listbox (React)
* add different render features (Vue)
* use render features in Menu and Listbox (Vue)
* bump dependencies
* add ability to change the ref property using `refName`
Example use case:
```tsx
// Some components have this API with an `innerRef`. The suggested approach is to use
// `React.forwardRef` so that you get the actual `ref` value. However if you already have this
// `innerRef` API than we can use the `refName="innerRef"` to give the `ref` prop a good name. It
// defaults to `ref` so that it still works everywhere else.
function MyButton({ innerRef, ...props }) {
return <button ref={innerRef} {...props} />
}
<Menu.Button as={MyButton} refName="innerRef" />
```
* small cleanup, move refs to props we control
* add tests for the render abstraction (Render)
+ use the unique __ symbol as a default value in the Props type for the
omitable props.
* use render features in Transition (React)
* add/update Transition examples to also showcase the `unmount={false}` render strategy
* bump dependencies
* add example with nested unmount/hide transitions
* add unmount to Transition documentation