Robin Malfait ef78d58a2e Fix crash when using DisclosureButton inside of a DisclosurePanel when the Disclosure is open by default (#3465)
This PR fixes an issue where React hooks were called unconditionally>

The `PopoverButton` and `DisclosureButton` act as a `CloseButton` when
used inside of a panel. We conditionally handled the `ref` when it's
inside a panel. To ensure that the callback is stable, the conditionally
used function was wrapped in a `useEvent(…)` hook.

This seemed to be ok (even though we break the rules of hooks) because a
button can only be in a panel or not be in a panel, but it can't switch
during the lifetime of the button. Aka, the rules of hooks are not
broken because all code paths lead to the same hooks being called.

```ts
<Disclosure defaultOpen>
  <DisclosureButton>Open</DisclosureButton>
  <DisclosurePanel>
    <DisclosureButton>Close</DisclosureButton>
  </DisclosurePanel>
<Disclosure>
```

But... it can be called conditionally, because the way we know whether
we are in a panel relies on a state value which comes from context and
is populated by a `useEffect(…)` hook.

The reason we didn't catch this in the `Disclosure` component, is
because all the state is stable and known by the time the
`DisclosurePanel` opens. But if you use the `defaultOpen` prop, the
`DisclosurePanel` is already open and then the state is not ready yet
(because we have to wait for the `useEffect(…)` hook).

Long story short, moved the `isWithinPanel` check inside the
`useEvent(…)` hook that holds the stable function which means that we
don't call this hook unconditionally anymore.
2024-09-09 21:13:45 +02:00
2024-05-02 14:41:58 +02: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
2024-09-04 16:36:30 +02:00
2024-05-02 14:41:58 +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%