Components: Sidenav and Toolbar buttons are highlighed automatically

Created on 21 Feb 2017  路  11Comments  路  Source: angular/components

Bug, feature request, or proposal:

Bug

What is the expected behavior?

When the sidenav is opened and the user move the cursor on one of buttons the first button is always highlighted automatically.

Moreover, when the sidenav is closed the menu button on the toolbar is highlighted automatically until the user click somewhere else.

What is the current behavior?

Highlights should be shown only if the user moves the cursor on button.

What are the steps to reproduce?

Plunker -> https://plnkr.co/edit/ve5Ez0WSinNyowxI46LO?p=preview

Which versions of Angular, Material, OS, browsers are affected?

"@angular/common": "2.4.7",
"@angular/compiler": "2.4.7",
"@angular/core": "2.4.7",
"@angular/flex-layout": "^2.0.0-beta.4",
"@angular/forms": "2.4.7",
"@angular/http": "2.4.7",
"@angular/material": "^2.0.0-beta.2",
"@angular/platform-browser": "2.4.7",
"@angular/platform-browser-dynamic": "2.4.7",
"@angular/platform-server": "2.4.7",

Is there anything else we should know?

P3 has pr

Most helpful comment

2018 update: I'm still having this problem 1 year later, I was able to solve it using a variation of @joh04667's hacks, adapted to the current angular version.

  • force the first button in the side nav to stay unfocused => still works
  • force the menu button outside the side nav to stay unfocused => calling _removeKeyboardFocus() didn't work for me, instead I came up with the following hack

template:

<mat-sidenav #sidenav (close)="handleClose(menuButton)">
  <!--...-->
</mat-sidenav>
<mat-sidenav-content>
  <button #menuButton mat-icon-button (click)="sidenav.toggle()">
    <mat-icon>menu</mat-icon>
  </button>
  <!--...-->
</mat-sidenav-content>

controller:

  @ViewChild('menuButton') menuButton: MatButton;

  handleClose = (button: MatButton) => {
    // <any> needed to satisfy ts compiler, otherwise it won't allow accessing MatButton's private methods
    (<any>button)._focusMonitor.stopMonitoring(button._getHostElement());
  }

Note that this is still a hack, so if someone knows a cleaner solution please, let me know!

All 11 comments

This is related to the md-button directive. The first md-button in the sidenav shows this behavior. As a workaround, you can set a 'dummy' anchor tag or button at the start of the sidenav with an md-button attribute, then set its height to 0 and position it absolutely.

EDIT:

More details:

When an element with md-button is hovered, the "mat-button-focus" class is being applied to the first element with an md-button attribute in the sidenav. The class stays there even as other md-buttons are hovered over, and is removed on a normal blur event (click, etc). This only affects elements with an md-button attribute.

When the sidenav is closed, the focus is applied to the button that opened the sidenav. Its position and parent container have no affect on this. Putting multiple buttons tied to the sidenav around the page, clicking one to open, and closing it always lead to the button that opened it getting focused.

Workaround:

As stated, the md-button focusing in the sidenav can be worked around by adding a dummy md-button element with no height, like so: https://plnkr.co/edit/wPWpZINvhfhyhViXc9Jt?p=preview

For the menu icon getting focused when the sidenav is closed, I bound the private _removeKeyboardFocus() method on the mdButton prototype to the md-sidenav's onClose event. Naughty naughty using private methods, I know, but that's why it's called a workaround.
Example fix for OP's Plunker: https://plnkr.co/edit/HvwUYtCQQ86ibhUFbXC8?p=preview

Just looked into this. It's WAI that the sidenav focuses the first focusable element upon opening, though as @joh04667 pointed out the md-button is treating the programmatic focus from the focus-trap as a keyboard focus and applying the keyboard focus styling. I'll prepare a PR to switch md-button over to using the new FocusOriginMonitor which handles this edge case.

@mmalerba just to be clear....it's WAI to have the keyboard focus only show up and stick to the first element when any md-button element is hovered over? And for it to lose keyboard focus when an empty space in the sidenav is clicked? This doesn't seem like a very good feature to me; the keyboard focus is not shown initially and is able to be removed trivially.

Here's a simpler Plunker with that behavior: https://plnkr.co/edit/wPWpZINvhfhyhViXc9Jt?p=preview

It's WAI for the first focusable element in the sidenav to be focused when the sidenav is opened. However buttons should only have the darkened background style when they are focused via they keyboard (i.e. pressing tab).

2018 update: I'm still having this problem 1 year later, I was able to solve it using a variation of @joh04667's hacks, adapted to the current angular version.

  • force the first button in the side nav to stay unfocused => still works
  • force the menu button outside the side nav to stay unfocused => calling _removeKeyboardFocus() didn't work for me, instead I came up with the following hack

template:

<mat-sidenav #sidenav (close)="handleClose(menuButton)">
  <!--...-->
</mat-sidenav>
<mat-sidenav-content>
  <button #menuButton mat-icon-button (click)="sidenav.toggle()">
    <mat-icon>menu</mat-icon>
  </button>
  <!--...-->
</mat-sidenav-content>

controller:

  @ViewChild('menuButton') menuButton: MatButton;

  handleClose = (button: MatButton) => {
    // <any> needed to satisfy ts compiler, otherwise it won't allow accessing MatButton's private methods
    (<any>button)._focusMonitor.stopMonitoring(button._getHostElement());
  }

Note that this is still a hack, so if someone knows a cleaner solution please, let me know!

Just noticed this as well... very odd behavior and definitely a bug we shouldn't have to account for

This might not be the best solution, but it seems like the easiest from what I have read. I just simply overrode the focus class (in my case, .mat-list-item-focus) to background-color: inherit !important; since it is just slightly changing the background color and isn't doing anything else. Then I made a custom class that I apply with routerLinkActive.

Obviously, this only works assuming you're using Angular routing, but could easily be modified to suit your situation.

2018 update: I'm still having this problem 1 year later, I was able to solve it using a variation of @joh04667's hacks, adapted to the current angular version.

  • force the first button in the side nav to stay unfocused => still works
  • force the menu button outside the side nav to stay unfocused => calling _removeKeyboardFocus() didn't work for me, instead I came up with the following hack

template:

<mat-sidenav #sidenav (close)="handleClose(menuButton)">
  <!--...-->
</mat-sidenav>
<mat-sidenav-content>
  <button #menuButton mat-icon-button (click)="sidenav.toggle()">
    <mat-icon>menu</mat-icon>
  </button>
  <!--...-->
</mat-sidenav-content>

controller:

  @ViewChild('menuButton') menuButton: MatButton;

  handleClose = (button: MatButton) => {
    // <any> needed to satisfy ts compiler, otherwise it won't allow accessing MatButton's private methods
    (<any>button)._focusMonitor.stopMonitoring(button._getHostElement());
  }

Note that this is still a hack, so if someone knows a cleaner solution please, let me know!

IMO a better way to handle this is to put the stopMonitoring line in ngOnInit in the containing component. Remove the close handler, add the ViewChild variable to your containing component, and in ngOnInit call of the enclosing component, put (menuButton)._focusMonitor.stopMonitoring(menuButton._getHostElement()); There's no need to call stopMonitoring every time you close the sidenav.

so is this issue still open? I can see the same issue with what I am doing right now..

I believe this is related to https://github.com/angular/material2/issues/10402? Found this thread via google long before that one and was stuck for a while.

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

_This action has been performed automatically by a bot._

Was this page helpful?
0 / 5 - 0 ratings

Related issues

RoxKilly picture RoxKilly  路  3Comments

MurhafSousli picture MurhafSousli  路  3Comments

constantinlucian picture constantinlucian  路  3Comments

3mp3ri0r picture 3mp3ri0r  路  3Comments

LoganDupont picture LoganDupont  路  3Comments