Search code examples
reactjstailwind-cssheadless-ui

How can I open a headless Tailwind dialog from inside a menu dropdown?


I'm using Tailwind CSS and their HeadlessUI components for React.

I'd like to be able to click an item in a menu dropdown and have it open a dialog. But when I click the item in the dropdown, the dialog flashes and disappears -- presumably it's closed because the dropdown menu was closed.

enter image description here

Is there a way to make this work?

The menu looks like this:

const menuItems = ['One', 'Two', 'Three', <Dialog />, 'Four']

// ...

<Headless.Menu as="div" className="relative inline-block text-left">
  <Headless.Menu.Button className="button">Menu</Headless.Menu.Button>
  <Headless.Menu.Items className="absolute mt-2 w-56 border divide-y rounded bg-white">
    {menuItems.map((item, i) => (
      <Headless.Menu.Item key={i}>
        {({ active }) => (
          <span
            className={cx({
              'block cursor-pointer px-4 py-2': true,
              'bg-gray-100 text-gray-900': active,
            })}
            children={item}
          />
        )}
      </Headless.Menu.Item>
    ))}
  </Headless.Menu.Items>
</Headless.Menu>

and the dialog:

const Dialog = ({ buttonStyle }: any) => {
  const [isOpen, setIsOpen] = useState(false)
  const open = () => setIsOpen(true)
  const close = () => setIsOpen(false)
  return (
    <>
      <button className={buttonStyle} onClick={open}>
        <b>👉 Click me 👈</b>
      </button>
      <Headless.Transition.Root show={isOpen}>
        <Headless.Dialog as="div" className="Dialog" onClose={close}>
          <Backdrop />
          <div className="fixed inset-0 z-10 flex min-h-full justify-center p-4 items-center">
            <Headless.Dialog.Panel className="w-full max-w-lg p-6 rounded bg-white space-y-2">
              <p className="text-4xl">🥳</p>
              <p>I am a dialog and you can see me.</p>
              <div className="text-right">
                <button className="button" onClick={close} children="OK" />
              </div>
            </Headless.Dialog.Panel>
          </div>
        </Headless.Dialog>
      </Headless.Transition.Root>
    </>
  )
}

You can see it in action here: https://tailwind-dialog-in-dropdown.glitch.me/

Code is here: https://glitch.com/edit/#!/tailwind-dialog-in-dropdown


Solution

  • You can fix this by making sure the menu isn't unmounted when it's closed, <Menu.Items> has a prop for this, so try:

    <Headless.Menu.Items unmount={false}>