Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement sibling <Dialog /> components #3242

Merged
merged 30 commits into from
May 27, 2024
Merged

Conversation

RobinMalfait
Copy link
Collaborator

@RobinMalfait RobinMalfait commented May 26, 2024

This PR refactors, restructures and simplifies some internal workings and as a side effect allows us to render "sibling dialogs" which has been a common request (and source of bugs) in the past.

The internals work by keeping track of a shared "stack", the moment an internal useIsTopLayer hook is used (and enabled) it adds an item to the stack. The hook then returns whether it currently is the top layer or not.

This allows us to render a <Dialog /> component from anywhere and the last one that is opened will be the top-most <Dialog /> (inspired by the native top-layer).

Pressing esc, or clicking outside of a <Dialog /> will close the top most one only regardless from where it was rendered.

This new internal hook is also used in other components such as the <Menu /> component. If you render a <Menu /> in a <Dialog />, then pressing esc only closes the <Menu />. Pressing esc again closes the <Dialog />. (This behavior already worked, but it now Just Works™ because of this)

This should not break any existing code where <Dialog /> components are nested because the inner one will be rendered after the outer one which makes it the top one.

Fixes: #2876

Copy link

vercel bot commented May 26, 2024

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
headlessui-react ✅ Ready (Inspect) Visit Preview 💬 Add feedback May 27, 2024 9:30pm
headlessui-vue ✅ Ready (Inspect) Visit Preview 💬 Add feedback May 27, 2024 9:30pm

By making use of the new `useHierarchy` hook.
They are now replaced by the new `useHierarchy` hook.
This way we can scope the hierarchy inside of the `useOutsideClick`
hook. This now ensures that we only enable the `useOutsideClick` on the
top-most element (the one that last enabled it).
No need to setup focus feature flags and then disable it all again if
demo mode is enabled.
@thecrypticace
Copy link
Contributor

This is not necessary.
Because it might not be super obvious that we are going to close the
`<Dialog />`.
This is necessary to make sure that a component like a `<MenuItems
anchor />` is rendered inside of the `<Dialog />` and not as a sibling.

While this all works from a functional perspective, if you rely on a
CSS variable that was defined on the `<Dialog />` and you use it in the
`<MenuItems />` then without this change it wouldn't work.
@dygaomarques
Copy link

dygaomarques commented Jun 14, 2024

Thhaaaaannkkkk yooouuuuuuu guys! 🎉

@wahyubaskara
Copy link

When this refactor will be applied to vue version?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

headlessui / When two modals are opened as brothers(not nested child)
4 participants