Material-components-web: Simple menu doesn't close when clicked outside of the menu on mobile

Created on 21 May 2017  路  10Comments  路  Source: material-components/material-components-web

What MDC-Web Version are you using?

 "@material/menu": "^0.2.6",

What browser(s) is this bug affecting?

Mobile Chrome and Mobile Safari on iOS

What OS are you using?

iOS 10.3.1

What are the steps to reproduce the bug?

  1. Open this demo page on mobile Safari
  2. click REVEAL MENU to open it
  3. Tap anywhere outside of the menu. See that menu is not closed.

What is the expected behavior?

Menu should be closed when tapped outside. That is the behavior on Google Chrome on desktop.

What is the actual behavior?

When clicked outside of a menu, it is not closed, nothing happens.

backlog bug

Most helpful comment

Found out this is because iOS doesn't emit a click event if the element you are tapping on isn't considered "clickable".

Workaround is setting all elements as "clickable"

@supports (-webkit-overflow-scrolling: touch) {
  /* CSS specific to iOS devices */
  * {
    cursor: pointer;
  }
}

All 10 comments

Thanks for catching it. Definitely a bug!

Comment from duplicate issue #843.

Click events normally do not bubble up to the html or body tags in iOS. If the body tag has a CSS cursor property set to pointer, a click event will after a delay eventually bubble, but this is too slow to be a feasible workaround.
Including a 'touchstart' as well as a 'click' handler in the simple menu registerBodyClickHandler() method will let the menu perform correctly, but this then means all adapter users would have to remember to do something similar. A better solution might be a breaking change to have the adapter have a registerBodyInteractionHandler( /* type: string, handler: EventListener */) and then the foundation could register multiple event types to watch for. (cf. mdc-menu that takes this approach with its registerBodyInteractionHandler())

It would also be handy that if you clicked outside to close the menu on a LINK, that link would be prevented.

It would also be handy that if you clicked outside to close the menu on a LINK, that link would be prevented.

What if the user meant to click the link to navigate away?

Are there any known a11y/UX recommendations from resources like the WCAG/ARIA groups to support preventing an anchor navigation in this context?

What if the user meant to click the link to navigate away?

Are there any known a11y/UX recommendations from resources like the WCAG/ARIA groups to support preventing an anchor navigation in this context?

@Garbee

This is functionality I have seen in a few of the Google Apps. For example, Google Plus / Notifications Bottom Nav Tab / Clicking the Page Title Filter.

It's handy in situations when the drop down takes up most of the view port and you want to dismiss.

Without some kind of investigation into whether that is expected usability/accessibility behavior it's probably best left out of the default base. Simply because various Google properties do certain things, doesn't necessarily mean they are the recommended way to handle things.

If you'd like to have that functionality within you're apps it is something that can be handled without the decision being made within the library. At least until we have confirmation of some kind that this what the UX pattern should be like.

@Garbee Yeah I understand that, I've just added it to my code for now. The Material Design specs are not 100% clear but I believe they lean towards this functionality. It just doesn't specifically say if there is another link 'outside the menu'.

"Dismiss a menu by tapping outside of the menu"

"The maximum height of a simple menu should be one or more rows less than the view height. This ensures a tappable area outside of the simple menu with which to dismiss the menu."

https://material.io/guidelines/components/menus.html#menus-behavior

While the current specs may not specify a behavior, we currently have inconsistent behavior. On non-mobile versions of Safari and Chrome, clicking outside the menu results in it's closing (due to the click event bubbling up). We are specifically putting a click event listener in place for this exact purpose.

On mobile devices, the click event does not bubble up (as already discussed) so the click event listener never fires, resulting in the menu not closing.

It would appear to me, the intention of the code was to allow the closing of the menu based on a click outside of the menu, based on the existence of a body click event listener. I would think, for consistency of expectation of the user, we should either:

  1. remove the event listener all together, or
  2. make it work on mobile devices

At a bare minimum, we should at least inform developers who are pulling in this component of this unexpected behavior:

  • in code,
  • in documentation, or
  • both.

Found out this is because iOS doesn't emit a click event if the element you are tapping on isn't considered "clickable".

Workaround is setting all elements as "clickable"

@supports (-webkit-overflow-scrolling: touch) {
  /* CSS specific to iOS devices */
  * {
    cursor: pointer;
  }
}

Given that you're listening for a click on the body to close a dropdown, it's enough to specify cursor: pointer on the body alone

@supports (-webkit-overflow-scrolling: touch) {
  body {
    // fix event bubbling
    cursor: pointer;

    // prevent flashes when tapping the body 
    // you may also need to add this rule on other page wrapping elements depending on your markup
    -webkit-tap-highlight-color: transparent;
  }
}
Was this page helpful?
0 / 5 - 0 ratings

Related issues

yapryntsev picture yapryntsev  路  3Comments

16rajumane picture 16rajumane  路  3Comments

jimyhdolores picture jimyhdolores  路  3Comments

trimox picture trimox  路  4Comments

traviskaufman picture traviskaufman  路  3Comments