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

[Menu] Improve hover/select/focus UI display #5186

Closed
rosskevin opened this issue Sep 15, 2016 · 18 comments · Fixed by #21930
Closed

[Menu] Improve hover/select/focus UI display #5186

rosskevin opened this issue Sep 15, 2016 · 18 comments · Fixed by #21930
Labels
bug 🐛 Something doesn't work component: menu This is the name of the generic UI component, not the React module! design: material This is about Material Design, please involve a visual or UX designer in the process priority: important This change can make a difference

Comments

@rosskevin
Copy link
Member

Problem description

After initial open of menu, first item remains highlighted even after hovering off.

Steps to reproduce

next branch, menus demo http://localhost:3000/#/component-demos/menus

  1. click to open
  2. hover to a lower item

Versions

next branch a38068f

  • Browser: Mac Chrome 52.0.2743.116
  • Browser: Mac Firefox 48.0.2
  • Browser: Mac Safari 9.1.2

Images

fullscreen_9_15_16__10_21_am

@oliviertassinari oliviertassinari changed the title next: Menu open leaves first item highlighted even though hovering on other item [Menu] open leaves first item highlighted even though hovering on other item Oct 2, 2016
ArcanisCz added a commit to ArcanisCz/material-ui that referenced this issue Feb 8, 2017
@oliviertassinari oliviertassinari added the component: menu This is the name of the generic UI component, not the React module! label Jul 4, 2017
@ArcanisCz
Copy link
Contributor

ArcanisCz commented Jul 16, 2017

@oliviertassinari Hi, sorry to be inactive for awhile!

Moving discussion from closed PR

I am not sure i understand Nathan...

Problem is with hover and different expexcted UX for touch and mouse devices. This way, when you open menu with something selected (first item is selected by default, but lets put this aside now), this remain selected until you click/touch another option. Alternatively, you can move your selected item with keyboard arrows.

Selected item has grey background. Hovered items also have grey background. So visually, you have 2 selected items when you move your mouse inside Menu (1 selected, 1 by hover). What should mouse hovering signify?

  1. my proposal in rejected PR was to tie together hover and select states, which is quite radical solution. But it solves this dichotomy.
  2. Both states could have different background color, and we will delete preselecting first option (keyboard actions with menu open will activate that though). This will solve problem with user perceiving 2 selected options.

Should i implement that 2) option?

@oliviertassinari
Copy link
Member

oliviertassinari commented Jul 16, 2017

@ArcanisCz I have been doing some benchmark, it's even worse than that. We have 3 possibles state. The focus, selected, and hover. You can have all of them at the same time:
capture d ecran 2017-07-16 a 19 14 59
Also, we should also consider where is the original focus, we focus the selected item or the first one

  • The native select input on chrome tie together the hover and select state but have a different style for the selected one:
    capture d ecran 2017-07-16 a 19 21 09

The selected item is focused by default, otherwise, the first one.

@oliviertassinari
Copy link
Member

I think that the best option is to keep the default focus behavior and to change the style of the three possible different states. I like the react-bootstrap solution (same as bootrap@4-alpha).

@blackdynamo
Copy link

blackdynamo commented Oct 17, 2017

I would also be interested in an option to not have the first value selected. You may want a menu that performs actions and you never select an item. In order to get my desired effect, I have had to do the following:

<MenuItem key="placeholder" style={{display: "none"}} />

This is always the first item in the list so it gets highlighted but you don't see it cause it's hidden. Although this works, it is not ideal.

@pjuke
Copy link

pjuke commented Nov 7, 2017

I would really like to see this feature. Currently I'm using a <Popover> with a <List> to get around it, which is not really optimal.

Above work-around would also work, but is not ideal.

@mbrookes
Copy link
Member

I think that the best option is to keep the default focus behavior and to change the style of the three possible different states.

In Google inbox, hover removes keyboard focus, so there is only ever one focused item. (Same as for Mac OS). For the Drawer list, they're using a slightly different shade for selected vs focus.

@oliviertassinari
Copy link
Member

@mbrookes The "three state" approach seems quite common:

  • angular material2
    capture d ecran 2017-12-31 a 16 10 06
  • Vuetify
    capture d ecran 2017-12-31 a 16 09 56
  • Amazon
    capture d ecran 2017-12-31 a 16 00 13
  • Bootstrap v4
    capture d ecran 2017-12-31 a 16 12 42
  • material-web-components
    capture d ecran 2017-12-31 a 16 14 37

I'm going with this approach.

@oliviertassinari
Copy link
Member

oliviertassinari commented Jun 21, 2018

The final approach:

  1. disabled
  2. focus
  3. selected
  4. hover

capture d ecran 2018-06-21 a 17 13 20

@oliviertassinari
Copy link
Member

The logic is no longer implemented, something has caused a regression, somewhere. We should take care of it. Also, it's a good opportunity to challenge what the best tradeoff is.

@oliviertassinari oliviertassinari removed their assignment Jun 22, 2019
@oliviertassinari oliviertassinari removed this from the release of v1.0.0 milestone Jun 22, 2019
@oliviertassinari oliviertassinari added the priority: important This change can make a difference label Jun 22, 2019
@joshwooding
Copy link
Member

@oliviertassinari Do you have a reproduction I can look at? I'm not sure what I'm looking for :)

@oliviertassinari
Copy link
Member

@joshwooding We have explored different approaches in #16331 (comment). What do you think of the approach n°1?

@eps1lon
Copy link
Member

eps1lon commented Oct 7, 2019

@joshwooding We have explored different approaches in #16331 (comment). What do you think of the approach n°1?

I want to double down on this quote:

We can challenge the need for these two states to have a different UI. I assume that most people use the mouse or the keyboard exclusively, rarely the two at the same time.

I completely agree here. One important part of a11y is that you consider focus(-visible) like any cursor. A sighted user can use the mouse to navigate to actions while screen reader users can use tab-focus. The focus outline marks the item that will be activated on-enter just like the hover marks the item that activates on mousedown. Enter and mousedown+up will both trigger a click event in the DOM. Styling hover and focus the same way is the only sensible thing if you think about it from a functional standpoint.

Since it's already hard enough to distinguish selected and focus I'd be perfectly fine with styling focus and hover the same way.

@oliviertassinari
Copy link
Member

oliviertassinari commented Oct 8, 2019

We can challenge the need for these two states to have a different UI. I assume that most people use the mouse or the keyboard exclusively, rarely the two at the same time.

@eps1lon Agree.


I have looked at the specification, I couldn't find any resources on the problem.
A new benchmark can help (selected, focused & hover states, in this order top-down):

Capture d’écran 2019-10-08 à 15 26 13
console.cloud.google.com

Capture d’écran 2019-10-08 à 15 28 02
studio.youtube.com (merge focus & hover)

Capture d’écran 2019-10-08 à 15 29 31
calendar.google.com (merge selected, focus & hover)

Capture d’écran 2019-10-08 à 15 34 10
ads.google.com (merge focus & hover)

Capture d’écran 2019-10-08 à 15 36 44
search.google.com (merge selected, focus & hover)


In this context, I would propose this fix:

diff --git a/packages/material-ui/src/ListItem/ListItem.js b/packages/material-ui/src/ListItem/ListItem.js
index d663d8934..9d11b30a3 100644
--- a/packages/material-ui/src/ListItem/ListItem.js
+++ b/packages/material-ui/src/ListItem/ListItem.js
@@ -23,7 +23,7 @@ export const styles = theme => ({
     paddingTop: 8,
     paddingBottom: 8,
     '&$focusVisible': {
-      backgroundColor: theme.palette.action.selected,
+      backgroundColor: theme.palette.action.hover,
     },
     '&$selected, &$selected:hover': {
       backgroundColor: theme.palette.action.selected,

We use to have this logic, it seems to have been lost (by mistake?) between #14680 and #14212. I'm not sure what I had in mind 🤔. Would it work for you guys?

@eps1lon
Copy link
Member

eps1lon commented Oct 14, 2019

Also interesting that native <select /> makes no distinction at all between hover and selected. Once you hover over the first item the "highlight cursor" will follow hover. In keyboard modality it will follow focus. Both modalities have different behavior with regard to selection state (mouse: selection does not follow hover, keyboard: selection does follow focus).

@oliviertassinari
Copy link
Member

oliviertassinari commented Oct 15, 2019

Also interesting that native <select /> makes no distinction at all between hover and selected.

@eps1lon On which environment? On macOS, I have:

selected
Capture d’écran 2019-10-15 à 13 34 10

hover/focused
Capture d’écran 2019-10-15 à 13 34 16

Regarding the multi-select use case, the keyboard focus state needs to take precedence over the selected state, otherwise, you can't see where your focus is if you have, let's say 3 options selected consecutively.

I would propose a slightly different version to #5186 (comment)

I like this tradeoff:

  • use the same style for hover/focus
  • keep the outline for keyboard focus to be visible when the item is selected
  • have the selected state to keep precedence over the hover/focus one.

What do you think?

diff --git a/packages/material-ui/src/ListItem/ListItem.js b/packages/material-ui/src/ListItem/ListItem.js
index d663d8934..dd03def41 100644
--- a/packages/material-ui/src/ListItem/ListItem.js
+++ b/packages/material-ui/src/ListItem/ListItem.js
@@ -23,7 +23,9 @@ export const styles = theme => ({
     paddingTop: 8,
     paddingBottom: 8,
     '&$focusVisible': {
-      backgroundColor: theme.palette.action.selected,
+      backgroundColor: theme.palette.action.hover,
+      outline: '2px solid #999',
+      outlineOffset: -2,
     },
     '&$selected, &$selected:hover': {
       backgroundColor: theme.palette.action.selected,

or

  • use the same style for hover/focus
  • have the hover/focus state to keep precedence over the selected one.
diff --git a/packages/material-ui/src/ListItem/ListItem.js b/packages/material-ui/src/ListItem/ListItem.js
index d663d8934..bf00ec1fe 100644
--- a/packages/material-ui/src/ListItem/ListItem.js
+++ b/packages/material-ui/src/ListItem/ListItem.js
@@ -22,11 +22,11 @@ export const styles = theme => ({
     textAlign: 'left',
     paddingTop: 8,
     paddingBottom: 8,
-    '&$focusVisible': {
+    '&$selected': {
       backgroundColor: theme.palette.action.selected,
     },
-    '&$selected, &$selected:hover': {
-      backgroundColor: theme.palette.action.selected,
+    '&$focusVisible': {
+      backgroundColor: theme.palette.action.hover,
     },
     '&$disabled': {
       opacity: 0.5,

@eps1lon
Copy link
Member

eps1lon commented Oct 28, 2019

What do you think?

I would need a render preview for that. Pure code is for UI/UX hard to review.

@oliviertassinari
Copy link
Member

@eps1lon OK, I will open a pull request after #17037 is merged. The multi-select case adds constraints on the scope of the solutions available.

@oliviertassinari oliviertassinari changed the title [Menu] open leaves first item highlighted even though hovering on other item [Menu] Improve hover/select/focus UI display Nov 29, 2019
@oliviertassinari oliviertassinari removed the priority: important This change can make a difference label Dec 1, 2019
@oliviertassinari
Copy link
Member

oliviertassinari commented Jan 21, 2020

We might have a recommendation from the specification:

Capture d’écran 2020-01-21 à 12 04 18

Capture d’écran 2020-01-21 à 12 06 39

https://material.io/design/interaction/states.html#anatomy

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug 🐛 Something doesn't work component: menu This is the name of the generic UI component, not the React module! design: material This is about Material Design, please involve a visual or UX designer in the process priority: important This change can make a difference
Projects
None yet
Development

Successfully merging a pull request may close this issue.

8 participants