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

fix(button): focus styles not applied to programmatically focused buttons #5966

Merged

Conversation

crisbeto
Copy link
Member

@crisbeto crisbeto commented Jul 22, 2017

Currently the tint that is added on top of focused buttons won't show up if the button is focused programmatically, which means that the button won't appear focused in cases like the dialog closing and restoring focus to its trigger. This seems to have been introduced by 5d6920d.

Fixes #7510.

@googlebot googlebot added the cla: yes PR author has agreed to Google's Contributor License Agreement label Jul 22, 2017
@mmalerba
Copy link
Contributor

So it sounds like the motivation for this change was a specific issue with the dialog closing. In general for most cases do you think programmatic focus should default to looking like keyboard or like mouse? If keyboard, we should make this change. Otherwise we should leave the styles the same and change dialog to inject FocusOriginMonitor and use the focusVia method to pretend it was a keyboard focus, since it's more of an exception than the normal case. I don't have a strong preference on what the default should be, just wanted to point out the difference and make sure we make whatever change we make deliberately.

@crisbeto
Copy link
Member Author

IMO all programmatic focus should look like the keyboard one, otherwise the user won't have any indication that something is focused. It's different for the mouse focus since the user is keeping track of their cursor and know what they clicked on so the indication isn't necessary.

@mmalerba
Copy link
Contributor

I think the reason I originally made it act like mouse is because of the situation where you click a button to open a sidenav and then the sidenav opens and programmatically focuses its first element. We didn't want the focus styles on that first element. But maybe we can consider that more of the exception case and add some code to do focusVia.

Also if we're going to do this for button let's be consistent, can you search our CSS for cdk-keyboard-focused and make sure that we always put the same styles for cdk-program-focused?

@crisbeto
Copy link
Member Author

Sure. I'll update this PR and ping you.

@crisbeto
Copy link
Member Author

Updated the 3 other cases we were using it @mmalerba.

@mmalerba
Copy link
Contributor

Can we change the sidenav to use focusVia so that we don't have a regressions with #3215? It's kinda tricky I think, because of the user opens the sidenav with the keyboard we want to show the focus style on the first element, but if they open it with the mouse we don't.

@crisbeto crisbeto force-pushed the programmatic-button-focus-style branch from 2f38ff4 to 32ad54c Compare July 29, 2017 09:18
@crisbeto
Copy link
Member Author

Done @mmalerba.

@@ -161,7 +162,7 @@ export class MdSidenav implements AfterContentInit, OnDestroy {
let activeEl = this._doc && this._doc.activeElement;
if (activeEl && this._elementRef.nativeElement.contains(activeEl)) {
if (this._elementFocusedBeforeSidenavWasOpened instanceof HTMLElement) {
this._elementFocusedBeforeSidenavWasOpened.focus();
this._focusOriginMonitor.focusVia(this._elementFocusedBeforeSidenavWasOpened, 'program');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is going to do the same thing that just calling .focus() was doing. I think we want logic like this:

  1. If the sidenav close is triggered by keyboard interaction (e.g. pressing escape) set it to keyboard focused
  2. If the sidenav close is triggered by mouse interaction (e.g. clicking on backdrop) set it to mouse focused
  3. If the sidenav close is triggered by directly calling close or toggle method allow the user to optionally supply the focus origin and default to program if they don't specify.

I think opening the sidenav needs similar logic but it's a little trickier because the sidenav isn't directly responsible for setting the focus on open, it goes through the focus trap.

You can test if this is working properly by opening and closing the sidenav in the demo app via different means and seeing what the resulting focus effect looks like

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure how that would work, considering that we don't have the equivalent of mdMenuTriggerFor for the sidenav. Alternatively, I can fix this only for the dialog where we have more control over the closing logic.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the closing logic I described is fairly straightforward to implement. For open you can just allow the user to pass an origin to the open method and it will default to program if they don't specify. That way if people really care about getting rid of the focus indicator they can add logic for it manually. It might also be nice to make a mdSidenavTrigger directive that does the focus origin logic for them.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That makes sense. I was trying to think of something that would work automagically.

@crisbeto
Copy link
Member Author

crisbeto commented Oct 8, 2017

Reworked this one based on what we discussed a while ago @mmalerba, can you take another look?

@mmalerba
Copy link
Contributor

mmalerba commented Oct 9, 2017

can you update the demo app's sidenav as well, to avoid this bug:

  1. click hamburger
  2. click new demo page in sidenav
  3. page loads & sidenav closes, observe focus style on hamburger menu after close (should not appear focused)

@crisbeto crisbeto force-pushed the programmatic-button-focus-style branch from 7ae7e0a to 5cc2417 Compare October 9, 2017 19:02
@crisbeto
Copy link
Member Author

crisbeto commented Oct 9, 2017

Done @mmalerba.

…tons

Currently the tint that is added on top of focused buttons won't show up if the button is focused programmatically, which means that the button won't appear focused in cases like the dialog closing and restoring focus to its trigger. This seems to have been introduced by 5d6920d.

Fixes angular#7510.
@crisbeto crisbeto force-pushed the programmatic-button-focus-style branch from 5cc2417 to bd52b35 Compare October 11, 2017 16:59
@crisbeto crisbeto added action: merge The PR is ready for merge by the caretaker and removed pr: needs rebase labels Oct 11, 2017
@andrewseguin andrewseguin merged commit a0bb1a3 into angular:master Oct 12, 2017
@angular-automatic-lock-bot
Copy link

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.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators Sep 7, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
action: merge The PR is ready for merge by the caretaker cla: yes PR author has agreed to Google's Contributor License Agreement
Projects
None yet
Development

Successfully merging this pull request may close these issues.

MdButton: 'focus()' API method doesn't focus the button
4 participants