base-ui icon indicating copy to clipboard operation
base-ui copied to clipboard

[Menu] Closes as soon as it's opened when extending the trigger's tap area with absolute-positioned element

Open benface opened this issue 1 month ago • 3 comments

Bug report

Current behavior

I believe it's a well known technique to extend the tap area of clickable elements that are too small (according to accessibility guidelines, usability testing, etc.) without affecting their layout or visual appearance by rendering an absolutely-positioned element inside them that bleeds out on each side. With Tailwind, we can do that with e.g. <span class="absolute -inset-4">. However, when that's done in a Menu.Trigger and we click on the "extended" part of the trigger, the menu closes as soon as it's opened:

https://github.com/user-attachments/assets/43f55c90-beba-4378-ad01-c2382464baf7

Expected behavior

Clicking on any part of Menu.Trigger, even when that part is outside the bounds of the button element, should open the menu without closing it instantly.

Reproducible example

https://codesandbox.io/p/devbox/laughing-glitter-w35dck

Base UI version

v1.0.0-beta.4

Which browser are you using?

Chrome, Safari, and Firefox

Which OS are you using?

macOS

Which assistive tech are you using (if applicable)?

N/A

Additional context

❤️

benface avatar Nov 11 '25 04:11 benface

Using a pseudo-element (after:content-[''] after:absolute after:-inset-8 after:bg-black/25) instead of a span to extend the trigger works as a workaround: https://codesandbox.io/p/sandbox/recursing-goodall-lxfjhl

mj12albert avatar Nov 11 '25 04:11 mj12albert

We handle pseudo-element bounds but not this one since we don't know where the element is located. The problem is the mouseup event target is the backdrop, while the clip-path "hole" only covers the trigger's bounds, which ignores the inner absolute element dimensions, so it doesn't detect the mouseup occurred inside the trigger since the backdrop is covering the extended hit area. Pseudo-elements suffer from this too, but we manually check their size to fix it.

This seems tough to fix, but as @mj12albert mentioned, there's a workaround, which we actually use on the docs:

Image

atomiks avatar Nov 11 '25 04:11 atomiks

Thank you for the explanation and for the workaround, @mj12albert and @atomiks. Unfortunately, it doesn't work in my case; the tap area element really needs to be a child because I have container style queries on it, and the container is the button. May I suggest the potential hacky solution of checking for nested elements with a particular data attribute, in addition to the ::before and ::after pseudo-elements?

benface avatar Nov 11 '25 15:11 benface