-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Description
Using
- @headlessui/react": "^2.2.0" - for both package and example app
In my example I have a package that I am working on that displays headlessui dialogs. When I try to use this package (e.g. in example app) in the app that uses headlessui on it's own, then closing the inner dialog (from the package) by clicking out closes the outer dialog (from the example app). When I have exactly the same code but just in one package everything works as expected.
The example code:
- Package code (inner modal)
import {
Dialog,
DialogBackdrop,
DialogPanel,
DialogTitle,
} from '@headlessui/react';
import { useState } from 'preact/hooks';
function InnerModal({
open,
setOpen,
}: {
open: boolean;
setOpen: (open: boolean) => void;
}) {
return (
<Dialog open={open} onClose={setOpen} className="relative z-30">
<DialogBackdrop
transition
className="fixed inset-0 bg-gray-500/75 transition-opacity data-closed:opacity-0 data-enter:duration-300 data-enter:ease-out data-leave:duration-200 data-leave:ease-in"
/>
<div className="fixed inset-0 z-30 w-screen overflow-y-auto">
<div className="flex min-h-full items-end justify-center p-4 text-center sm:items-center sm:p-0">
<DialogPanel
transition
className="relative transform overflow-hidden rounded-lg bg-white px-4 pt-5 pb-4 text-left shadow-xl transition-all data-closed:translate-y-4 data-closed:opacity-0 data-enter:duration-300 data-enter:ease-out data-leave:duration-200 data-leave:ease-in sm:my-8 sm:w-full sm:max-w-lg sm:p-6 data-closed:sm:translate-y-0 data-closed:sm:scale-95"
>
<div className="sm:flex sm:items-start">
<div className="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left">
<DialogTitle
as="h3"
className="text-base font-semibold text-gray-900"
>
Inner modal
</DialogTitle>
</div>
</div>
<div className="mt-5 sm:mt-4 sm:flex sm:flex-row-reverse">
<div className="sm:ml-3 sm:w-auto">
<button onClick={() => setOpen(false)}>Confirm</button>
</div>
<div className="mt-3 sm:mt-0 sm:w-auto">
<button data-autofocus onClick={() => setOpen(false)}>
Cancel
</button>
</div>
</div>
</DialogPanel>
</div>
</div>
</Dialog>
);
}
export default function InnerComponent() {
const [open, setOpen] = useState(false);
return (
<div>
<button onClick={() => setOpen(true)}>Open</button>
<InnerModal open={open} setOpen={setOpen} />
</div>
);
}
- Example app (outer modal)
import { useState } from 'preact/hooks';
import InnerComponent from 'react-importer';
import {
Dialog,
DialogBackdrop,
DialogPanel,
DialogTitle,
} from '@headlessui/react';
import { XMarkIcon } from '@heroicons/react/24/outline';
import { ReactNode } from 'preact/compat';
function OuterModal({
open,
setOpen,
children,
}: {
open: boolean;
setOpen: (open: boolean) => void;
children?: ReactNode;
}) {
return (
<Dialog open={open} onClose={setOpen} className="relative z-10">
<DialogBackdrop
transition
className="fixed inset-0 z-20 bg-gray-500/75 transition-opacity data-closed:opacity-0 data-enter:duration-300 data-enter:ease-out data-leave:duration-200 data-leave:ease-in"
/>
<div className="fixed inset-0 z-20 w-screen overflow-y-auto">
<div className="flex min-h-full items-end justify-center p-4 text-center sm:items-center sm:p-0">
<DialogPanel
transition
className="relative w-full max-w-4xl transform overflow-hidden rounded-lg bg-white px-4 pt-5 pb-4 text-left shadow-xl transition-all data-closed:translate-y-4 data-closed:opacity-0 data-enter:duration-300 data-enter:ease-out data-leave:duration-200 data-leave:ease-in sm:my-8 sm:p-6 data-closed:sm:translate-y-0 data-closed:sm:scale-95"
>
<div className="absolute top-0 right-0 hidden pt-4 pr-4 sm:block">
<button
type="button"
onClick={() => setOpen(false)}
className="cursor-pointer rounded-md bg-white text-gray-400 hover:text-gray-500 focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 focus:outline-hidden"
>
<span className="sr-only">Close</span>
<XMarkIcon aria-hidden="true" className="size-6" />
</button>
</div>
<div className="sm:flex sm:items-start">
<div className="mt-3 text-center sm:mt-0 sm:text-left">
<DialogTitle
as="h3"
className="text-base font-semibold text-gray-900"
>
Outer modal
</DialogTitle>
</div>
</div>
{children && <div className="mt-5">{children}</div>}
</DialogPanel>
</div>
</div>
</Dialog>
);
}
const App = () => {
const [open, setOpen] = useState(false);
return (
<div className="min-h-screen w-full">
<button onClick={() => setOpen(true)}>Open</button>
<OuterModal open={open} setOpen={setOpen}>
<div>
<InnerComponent />
</div>
</OuterModal>
</div>
);
};
export default App;
When I try to click out to close the inner modal, it closes the outer modal.
Interestingly when I replace outers modal setOpen with an empty function, then even the inner modal doesn't close when I click out. As if the outer modal swallows the click event and doesn't bubble it to the inner modal.
Is there something I am doing wrong in here? How could I make it work?