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(dialog): restore focus with the proper focus origin #9257

Merged

Conversation

devversion
Copy link
Member

  • Restores the trigger focus upon dialog close with the proper focus origin that caused the dialog closing.

For example, a backdrop click leads to a focus restore via mouse. Pressing escape leads to a focus restore via keyboard.

References #8420

@googlebot googlebot added the cla: yes PR author has agreed to Google's Contributor License Agreement label Jan 6, 2018
@devversion devversion force-pushed the fix/dialog-restore-focus-proper-origin branch from aaef71b to 48df402 Compare January 10, 2018 18:49
@devversion
Copy link
Member Author

Addressed the feedback and also added the check for the matDialogClose we discussed in the standup.

Copy link
Member

@jelbourn jelbourn left a comment

Choose a reason for hiding this comment

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

LGTM

@jelbourn jelbourn added pr: lgtm action: merge The PR is ready for merge by the caretaker and removed pr: needs review labels Jan 10, 2018
@devversion devversion added the target: patch This PR is targeted for the next patch release label Jan 10, 2018
@devversion devversion force-pushed the fix/dialog-restore-focus-proper-origin branch from 259cad2 to 3327650 Compare January 27, 2018 14:51
@mmalerba
Copy link
Contributor

@devversion please rebase

@devversion devversion force-pushed the fix/dialog-restore-focus-proper-origin branch from 3327650 to dabfa26 Compare April 17, 2018 17:33
@devversion
Copy link
Member Author

@mmalerba Done.

@andrewseguin andrewseguin added the presubmit failures This PR has failures in Google's internal presubmit process and cannot be immediately merged label Apr 26, 2018
@ngbot
Copy link

ngbot bot commented Jun 7, 2018

Hi @devversion! This PR has merge conflicts due to recent upstream merges.
Please help to unblock it by resolving these conflicts. Thanks!

1 similar comment
@ngbot
Copy link

ngbot bot commented Jun 7, 2018

Hi @devversion! This PR has merge conflicts due to recent upstream merges.
Please help to unblock it by resolving these conflicts. Thanks!

@angular angular deleted a comment from Carniatto Jun 26, 2018
@josephperrott josephperrott added pr: needs rebase and removed action: merge The PR is ready for merge by the caretaker labels Jun 26, 2018
@devversion devversion force-pushed the fix/dialog-restore-focus-proper-origin branch from dabfa26 to 67edd91 Compare June 28, 2018 18:37
@devversion
Copy link
Member Author

@josephperrott Rebased that one. Can we retry a presubmit in the future?

@devversion devversion force-pushed the fix/dialog-restore-focus-proper-origin branch from c8f02e9 to 67541e2 Compare June 25, 2019 15:15
@devversion
Copy link
Member Author

@jelbourn @josephperrott I rebased this one again. should we proceed with that one or don't you think it's worth moving forward with that? It definitely seems like a reasonable a11y feature for the dialog to me.

@devversion devversion added the action: merge The PR is ready for merge by the caretaker label Jun 25, 2019
@jelbourn jelbourn added the P2 The issue is important to a large percentage of users, with a workaround label Jun 26, 2019
@zelliott
Copy link
Collaborator

Just a quick bump that it would be awesome to get this in.

@devversion devversion force-pushed the fix/dialog-restore-focus-proper-origin branch from 67541e2 to b34c034 Compare January 22, 2020 11:19
@devversion
Copy link
Member Author

Rebased again. If we decide to move forward with this, then the changes should most likely also be ported over to the cdk-experimental/dialog version.

@devversion devversion added G This is is related to a Google internal issue needs rebase labels May 25, 2020
@andrewseguin
Copy link
Contributor

@devversion Want to move forward with this PR? If so, this is our next oldest P2 and I'm going to make it my side project to get a green presubmit with it.

@devversion devversion force-pushed the fix/dialog-restore-focus-proper-origin branch from b34c034 to 60c6895 Compare June 18, 2020 09:23
@devversion
Copy link
Member Author

@andrewseguin That would be awesome. I've rebased the PR. Let me know if I can help somehow!

@devversion devversion force-pushed the fix/dialog-restore-focus-proper-origin branch from 60c6895 to 82523fc Compare June 18, 2020 17:17
@andrewseguin
Copy link
Contributor

We're at a fork in the roads on this PR. This breaks a lot of internal tests.

Many tests provide a fake dialog ref using jasmine, e.g.

const dialogRefSpy = jasmine.createSpyObj('MatDialogRef', ['close']);

Then in their test, they check that close was called:

expect(dialogRefSpy.close).toHaveBeenCalledWith(false);

This change breaks that because now MatDialogClose calls _closeVia instead of close, so their expectation fails.

The "right thing to do" is to provide a fake for users so they don't need to make their own. Then they can just verify through the fake that expect(fakeDialogRef.closeResult).toBe(expectation). However, there are 1000+ instances of this internally, and it's going to take so many hours/days dedicated to migrate the tests.

An alternative path forward is to change this code a bit so that (click) still calls close(), but first sets some state through the MatDialogRef. For example, you can change _onButtonClick to be:

_onButtonClick(event: MouseEvent) {
    // Determinate the focus origin using the click event, because using the FocusMonitor will
    // result in incorrect origins. Most of the time, close buttons will be auto focused in the
    // dialog, and therefore clicking the button won't result in a focus change. This means that
    // the FocusMonitor won't detect any origin change, and will always output `program`.
    // [Plus additional comment on why we are setting this directly into the ref]
    this.dialogRef._closeInteractionType = event.screenX === 0 && event.screenY === 0 ? 'keyboard' : 'mouse';
    this.dialogRef.close(this.dialogResult);
  }

Then during close, the dialogRef would pass along that _closeInteractionType onto the container (or just do it from this function). This way, the API is preserved and all tests in Google would pass since close is still being called directly from the close directive.

This is obviously not ideal or best practice to be setting some state before calling a function, but a comment could be provided to explain why this is the case, as well as an additional test that makes sure we don't regress.

I still think it would be valuable to provide a fake to our users, but at least this won't be blocked on that migration occurring, which could possibly never get prioritized.

@devversion devversion force-pushed the fix/dialog-restore-focus-proper-origin branch from 82523fc to 682b751 Compare July 3, 2020 08:38
@devversion
Copy link
Member Author

@andrewseguin Thanks for looking into this. I've made the changes as discussed. Instead of manually assigning _closeInteractionType all the time, I've created an internal helper function that takes care of this. This will also allow us to easily remove this logic in the future if we ever sort these dialog ref mock complications out.

Restores the trigger focus upon dialog close with the proper focus origin that caused the dialog closing.
For example, a backdrop click leads to a focus restore via `mouse`. Pressing `escape` leads to a focus restore
via `keyboard`. Clicking the `matDialogClose` button will depend on the type of interaction (e.g. `click` or `keyboard`)

References angular#8420.
@devversion devversion force-pushed the fix/dialog-restore-focus-proper-origin branch from 682b751 to b795853 Compare July 6, 2020 06:45
@mmalerba mmalerba merged commit cf9bb1f into angular:master Jul 11, 2020
mmalerba pushed a commit that referenced this pull request Jul 11, 2020
Restores the trigger focus upon dialog close with the proper focus origin that caused the dialog closing.
For example, a backdrop click leads to a focus restore via `mouse`. Pressing `escape` leads to a focus restore
via `keyboard`. Clicking the `matDialogClose` button will depend on the type of interaction (e.g. `click` or `keyboard`)

References #8420.
@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 Aug 11, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Accessibility This issue is related to accessibility (a11y) action: merge The PR is ready for merge by the caretaker cla: yes PR author has agreed to Google's Contributor License Agreement G This is is related to a Google internal issue P2 The issue is important to a large percentage of users, with a workaround target: patch This PR is targeted for the next patch release
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants