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

[Select, Menu] Handle pseudo-element bounds in mouseup detection #1250

Merged
merged 12 commits into from
Jan 7, 2025

Conversation

onehanddev
Copy link
Contributor

@onehanddev onehanddev commented Dec 31, 2024

Below changes were made for Select and Menu components for their use[Menu/Select]trigger hook -

  • Add getPseudoElementPadding utility to measure ::before and ::after dimensions
  • Update mouseup detection logic to include pseudo-element padding in clickable area
  • Fix unexpected Select closing when clicking within extended pseudo-element bounds

Fixes #1232

- Add getPseudoElementPadding utility to measure ::before and ::after dimensions
- Update mouseup detection logic to include pseudo-element padding in clickable area
- Fix unexpected Select closing when clicking within extended pseudo-element bounds

Fixes mui#1232
@mui-bot
Copy link

mui-bot commented Dec 31, 2024

Netlify deploy preview

https://deploy-preview-1250--base-ui.netlify.app/

Generated by 🚫 dangerJS against 2a201d5

- Add getPseudoElementPadding utility to compute ::before/::after dimensions
- Refactor mouseup handler to check extended clickable area
- Update click detection logic to include pseudo-element padding
- Improve trigger bounds calculation for more accurate click handling

Fixes mui#1232 - Prevents menu from closing unexpectedly when clicking within
the pseudo-element extended area of the trigger.
@onehanddev
Copy link
Contributor Author

onehanddev commented Dec 31, 2024

@atomiks I believe these changes might work better if we move the entire handleMouseUp and getPseudoElementPadding logic to a common place, as the behavior seems consistent. What do you think?

@onehanddev onehanddev marked this pull request as ready for review December 31, 2024 09:44
@onehanddev
Copy link
Contributor Author

CircleCI is failing JSDOM test, I guess rerunning it should the fix the issue.

@onehanddev onehanddev changed the title fix(Select): handle pseudo-element bounds in mouseup detection fix(Select, Menu): handle pseudo-element bounds in mouseup detection Dec 31, 2024
@zannager zannager added component: select This is the name of the generic UI component, not the React module! component: menu This is the name of the generic UI component, not the React module! labels Jan 1, 2025
Comment on lines 103 to 121
function getPseudoElementPadding(triggerRefElement: HTMLElement) {
const beforeStyles = window.getComputedStyle(triggerRefElement, '::before');
const afterStyles = window.getComputedStyle(triggerRefElement, '::after');

const hasPseudoElements =
beforeStyles.content !== 'none' || afterStyles.content !== 'none';

const padding = hasPseudoElements
? Math.max(
parseInt(beforeStyles.width || '0', 10),
parseInt(afterStyles.width || '0', 10),
parseInt(beforeStyles.height || '0', 10),
parseInt(afterStyles.height || '0', 10),
) / 2
: 0;

return padding;
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for your contribution!

This could be refactored into a utility function (and technically, parts of the rest of the function too) to reuse between Menu and Select.

  • Given the padding can be asymmetric, this wouldn't actually measure it correctly I think, e.g. if left has 0px while right has 20px. Maybe instead of considering it as padding, you just check the max between the trigger rect width/height along with the pseudo elements' width/height
  • parseFloat(beforeStyles.width) || 0 is a simpler and more accurate function to use than parseInt

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the detailed review @atomiks
I have made these changes except I was a bit skeptical about moving the final checks to a utility function (see: technically, parts of the rest of the function too) as it was abstracting the code a bit much, Please take a look at the updated code and let me know if you think it still needs to be more reusable.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's ok, and I see that determining asymmetry on a given axis might not be feasible, so it's ok to assume it's symmetric.

However I still see the bug with the CSS modules selector on the docs, if I click on the bottom-left corner or right at the left edge, it still closes. Maybe floating point errors or something else?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes its indeed a minor floating point error, I assume it should be fixed with Math.round, let me try that and push the fix.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you please check the latest commit @atomiks Thanks !

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I cleared cache, and incognito is the same

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just saw your earlier comment, Let me just add +1 -1 to see if the issue fixes for you.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just made above change. Feel free to recheck the preview URL.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Debugged locally - we'll need 2 pixels, not 1. In fact I remember needing to use 2px for other things related to mouse events, and it works in all cases.

Screenshot 2025-01-06 at 10 56 49 pm

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, Done 👍

@michaldudak michaldudak changed the title fix(Select, Menu): handle pseudo-element bounds in mouseup detection [Select, Menu] Handle pseudo-element bounds in mouseup detection Jan 6, 2025
@atomiks atomiks merged commit 2f1205a into mui:master Jan 7, 2025
23 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
component: menu This is the name of the generic UI component, not the React module! component: select This is the name of the generic UI component, not the React module!
Projects
None yet
4 participants