material-ui
material-ui copied to clipboard
[Menu][Joy] Fix closing of `Menu` in demos
closes https://github.com/mui/material-ui/issues/36821
https://deploy-preview-36917--material-ui.netlify.app/joy-ui/react-menu/#basic-usage
- [ ] I have followed (at least) the PR section of the contributing guide.
Netlify deploy preview
Bundle size report
Generated by :no_entry_sign: dangerJS against 4f14a905cd7a8aa53b07fb728af4033b4ffd0959
@sai6855 Thanks for looking into this but I think it is not fixed because onMouseDown the popup is closed and then click event fires which will open the popup again.
https://user-images.githubusercontent.com/18292247/234159055-54c52d70-e164-4470-8300-a5a6a16b2841.mov
@siriwatknp updated logic, can you verify now.
In this PR ,Menu will be closed when you perform one of below actions
- click on
Buttonwhich opensMenu - Again clicking
ButtonclosesMenu
(Or)
- Click on
Buttonwhich opensMenu - Clicking on
areaoutside ofMenuandButtonclosesMenu
(Or)
onMouseDownonButtonwhich opensMenuand release themouse(Here menu should be opened)- perform same action as
1, nowMenuwill be closed
Right now on master only 2 nd case is working as expected
Please add a brief description of breaking changes along with instructions how to update existing codebases to the first comment of this PR.
As suggested added Keyboard and FocusEvent types to event here but there is a catch,Keyboard event type doesn't have relatedTarget property, so had to cast event type here to make typescript happy when accessing event.relatedTarget in demos.
Alternatively instead of casting event type, we can add a additional check demos like below.
const handleClose = (
event:
| React.MouseEvent<Element, Event>
| React.FocusEvent
| null
| React.KeyboardEvent<Event>,
) => {
if (event && 'relatedTarget' in event && event.relatedTarget !== anchorEl) {
setAnchorEl(null);
}
};
I'd appreciate your view here on what should be way forward. cc @michaldudak @siriwatknp
@sai6855 I have another idea (non-breaking change) for the fix. If my understanding is correct, the problem is
- when the menu is open
- mouse down on the button triggers
blurevent which change the open tofalseinmenuReducer - mouse up triggers click event which set the state from to
trueagain.
I wonder if it makes sense to not change open to false if the relatedTarget has aria-controls the same id as the listbox.
diff --git a/packages/mui-base/src/useMenu/menuReducer.ts b/packages/mui-base/src/useMenu/menuReducer.ts
index 9a0ac7b240..ac383e102d 100644
--- a/packages/mui-base/src/useMenu/menuReducer.ts
+++ b/packages/mui-base/src/useMenu/menuReducer.ts
@@ -35,6 +35,11 @@ export default function menuReducer(
if (action.type === ListActionTypes.blur) {
if (!action.context.listboxRef.current?.contains(action.event.relatedTarget)) {
+ const listboxId = action.context.listboxRef.current?.getAttribute('id');
+ const controlledBy = action.event.relatedTarget?.getAttribute('aria-controls');
+ if (listboxId && controlledBy && listboxId === controlledBy) {
+ return newState;
+ }
return {
...newState,
open: false,
This seems to work on my side.
@siriwatknp This looks fine to me! I'd only add a comment to explain what is this for as it's not obvious at first glance.
Also, it doesn't work on Joy demos when I apply this change on the latest master as id is not set there.
Might need to update the docs to say "aria-controls" and "id" is required.
you want this to be displayed for all demos or at the top of demos?
Might need to update the docs to say "aria-controls" and "id" is required.
you want this to be displayed for all demos or at the top of demos?
How about adding it to the introduction section at the top?
@siriwatknp added description here https://deploy-preview-36917--material-ui.netlify.app/joy-ui/react-menu/#introduction