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

PopoverButton hogs the event - cannot use as prop with Link #3561

Open
sstackus opened this issue Nov 18, 2024 · 1 comment
Open

PopoverButton hogs the event - cannot use as prop with Link #3561

sstackus opened this issue Nov 18, 2024 · 1 comment

Comments

@sstackus
Copy link

What package within Headless UI are you using?

@headlessui/react

What version of that package are you using?

v2.2.0

What browser are you using?

Firefox

Reproduction URL

https://codesandbox.io/p/devbox/morning-sea-9zfs2r

Describe your issue

PopoverButton takes an as prop which can be a custom component but presumably event.preventDefault() is called within the click handler, preventing any default behaviour that you may have, e.g. if you want to render a link instead of a button:

<PopoverButton as={MyLinkComponent} href="/">...</PopoverButton>

The logical next solution is to then just avoid as and render my custom component as a child:

<PopoverButton>
  <MyLinkComponent href="/" />
</PopoverButton>

However, this results in:

<button>
  <a></a>
</button>

which is obviously not right.

You can do <PopoverButton as="div"> but that's not right either, since for accessibility reasons you should not have a clickable div.

Okay, so then maybe PopoverButton insists that, because it's a clickable trigger, it must be a button - it's in the name, right? So then there should be no as prop at all?

If you want to have anything other than a button as your popover trigger, you're at a bit of an impasse.

Seems like there should be an imperative way to toggle the popover's state.


Link is one example but there very well could be cases that we cannot foresee. Behaviour like this should be left unrestricted, for the implementer to decide.

@sstackus
Copy link
Author

sstackus commented Nov 18, 2024

Just figured this out. Still kind of an issue though.

If in your custom component which you pass in as={Component} you have a click event handler, anything at all, then the event is not prevented, and the default browser behaviour proceeds, i.e.:

const MyPopoverButton = () => {
  return <PopoverButton as={MyLinkComponent} href="/">...</PopoverButton>;
};

const MyLinkComponent = forwardRef(({ children, ...props }, ref) => {
  return (
    <a
      {...props}
      ref={ref}
      onClick={() => {}} // <-- THIS GUY RIGHT HERE
    >
      {children}
    </a>
  );
});

Happy to have figured out a workaround for now, and I get why it would have been done this way, but still, this is rather bizarre.

@sstackus sstackus changed the title PopoverButton hogs the event - cannot freely use its as prop PopoverButton hogs the event - cannot use as prop with Link Nov 18, 2024
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

No branches or pull requests

1 participant