I'm using Tailwind CSS and the HeadlessUI Menu component for React.
The menu items are components that each contain a button that opens a dialog.
This works correctly when using the menu with the mouse. But when using the menu with the keyboard, the Menu component doesn't know to trigger an onClick
event on the buttons contained in DataImporter
and DataGenerator
, so nothing happens when you press Enter
.
Here's a stripped-down example:
import { useState, Fragment, useRef, ReactElement } from 'react'
import cx from 'classnames'
import * as Headless from '@headlessui/react'
export const App = () => {
const menuItems = [<DataImporter />, <DataGenerator />]
return (
<div className="flex flex-col space-y-4 border divide-y w-full max-w-lg bg-white">
<div className="p-10 space-y-4">
<Headless.Menu as="div" className="relative inline-block text-left">
<Headless.Menu.Button className="button">Menu</Headless.Menu.Button>
<Headless.Menu.Items
unmount={false}
static
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>
</div>
</div>
)
}
const DataImporter = () => {
const [isOpen, setIsOpen] = useState(false)
const open = () => setIsOpen(true)
const close = () => setIsOpen(false)
return (
<>
<button onClick={open}>Import data</button>
<Headless.Transition.Root show={isOpen}>
<Headless.Dialog as="div" 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">
<h3>Import data</h3>
<div className="text-right">
<button className="button" onClick={close} children="OK" />
</div>
</Headless.Dialog.Panel>
</div>
</Headless.Dialog>
</Headless.Transition.Root>
</>
)
}
const DataGenerator = () => {
const [isOpen, setIsOpen] = useState(false)
const open = () => setIsOpen(true)
const close = () => setIsOpen(false)
return (
<>
<button onClick={open}>Generate data</button>
<Headless.Transition.Root show={isOpen}>
<Headless.Dialog as="div" 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">
<h3>Generate data</h3>
<div className="text-right">
<button className="button" onClick={close} children="OK" />
</div>
</Headless.Dialog.Panel>
</div>
</Headless.Dialog>
</Headless.Transition.Root>
</>
)
}
const Backdrop = () => (
<div className="fixed inset-0 bg-gray-500 bg-opacity-75 transition-opacity" />
)
There's a live example here: https://oil-gorgeous-haze.glitch.me
Source code here: http://glitch.com/edit/#!/oil-gorgeous-haze?path=src%2FApp.tsx%3A58%3A0
Is there a way to get the MenuItem
component to trigger the onClick
event on the button contained in either of the dialog components?