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

[Menu][Joy] Fix closing of `Menu` in demos

Open sai6855 opened this issue 2 years ago • 5 comments

closes https://github.com/mui/material-ui/issues/36821

https://deploy-preview-36917--material-ui.netlify.app/joy-ui/react-menu/#basic-usage

sai6855 avatar Apr 17 '23 17:04 sai6855

Netlify deploy preview

Bundle size report

Details of bundle changes

Generated by :no_entry_sign: dangerJS against 4f14a905cd7a8aa53b07fb728af4033b4ffd0959

mui-bot avatar Apr 17 '23 17:04 mui-bot

@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 avatar Apr 25 '23 02:04 siriwatknp

@siriwatknp updated logic, can you verify now.

In this PR ,Menu will be closed when you perform one of below actions

  1. click on Button which opens Menu
  2. Again clicking Button closes Menu

(Or)

  1. Click on Button which opens Menu
  2. Clicking on area outside of Menu and Button closes Menu

(Or)

  1. onMouseDown on Button which opens Menu and release the mouse (Here menu should be opened)
  2. perform same action as 1, now Menu will be closed

Right now on master only 2 nd case is working as expected

sai6855 avatar Apr 25 '23 10:04 sai6855

Please add a brief description of breaking changes along with instructions how to update existing codebases to the first comment of this PR.

michaldudak avatar Apr 28 '23 07:04 michaldudak

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 avatar Apr 28 '23 16:04 sai6855

@sai6855 I have another idea (non-breaking change) for the fix. If my understanding is correct, the problem is

  1. when the menu is open
  2. mouse down on the button triggers blur event which change the open to false in menuReducer
  3. mouse up triggers click event which set the state from to true again.

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 avatar May 29 '23 11:05 siriwatknp

@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.

michaldudak avatar Jun 12 '23 12:06 michaldudak

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?

sai6855 avatar Jun 15 '23 08:06 sai6855

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 avatar Jun 15 '23 12:06 siriwatknp

@siriwatknp added description here https://deploy-preview-36917--material-ui.netlify.app/joy-ui/react-menu/#introduction

sai6855 avatar Jun 15 '23 13:06 sai6855