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

[Overlay] Enforce focus after backdrop mouse down #1330

Merged
merged 2 commits into from
Jul 28, 2017
Merged

Conversation

llorca
Copy link
Contributor

@llorca llorca commented Jul 8, 2017

Fixes #1324

Checklist

  • Include tests

@blueprint-bot
Copy link

Enforce focus after backdrop mouse down

Preview: documentation
Coverage: core | datetime

safeInvoke(onClose, e);
}
if (enforceFocus) {
// make sure document.activeElement is updated before bringing the focus back
Copy link
Contributor

Choose a reason for hiding this comment

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

not sure I understand this comment -- what's the "before" part about? isn't it updating document.activeElement by bringing the focus back?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Kind of the same problem than in Select and MultiSelect: https://github.com/palantir/blueprint/pull/1275/files#diff-61619f2144645e953195b1eadae9ceadR199

In both this case and the one from the URL above, document.activeElement isn't the expected value after clicking away. From what I understand, rAF allows to wait for the next frame at which point activeElement is the correct value.

Copy link
Contributor

Choose a reason for hiding this comment

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

rAF is decidedly not "the next frame," but the last possible moment of the same frame: before the next repaint. it lets us execute some logic after DOM updates but before repainting (to avoid flicker).

}
if (enforceFocus) {
// make sure document.activeElement is updated before bringing the focus back
requestAnimationFrame(() => this.bringFocusInsideOverlay());
Copy link
Contributor

Choose a reason for hiding this comment

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

why do we need requestAnimationFrame?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Copy link
Contributor

@adidahiya adidahiya Jul 26, 2017

Choose a reason for hiding this comment

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

that link demonstrates setTimeout, which potentially makes more sense here (as noted in the other comment thread, rAF is not the next frame).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We're already using rAF everywhere else we need the updated document.activeElement after triggering an event. Happy to change across the board to maintain consistency, I'll let you and @giladgray decide which is best and I'll open a separate PR if necessary

Copy link
Contributor

Choose a reason for hiding this comment

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

we've enjoyed success using rAF for focus things, more than with setTimeout because it executes later in the same frame. i support this.

if (canOutsideClickClose) {
safeInvoke(onClose, e);
}
if (enforceFocus) {
Copy link
Contributor

Choose a reason for hiding this comment

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

would be super great to add a unit test for this case. we have others for enforceFocus, should be a matter of copy-and-edit.

Copy link
Contributor Author

@llorca llorca Jul 10, 2017

Choose a reason for hiding this comment

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

Failing so far. What I have:

it("returns focus to overlay after clicking the backdrop if enforceFocus=true", () => {
    wrapper = mount(
        <Overlay enforceFocus={true} canOutsideClickClose={false} inline={true} isOpen={true}>
            {createOverlayContents()}
        </Overlay>,
    );
    wrapper.find(BACKDROP_SELECTOR).simulate("mousedown");
    assert.equal(document.querySelector(BACKDROP_SELECTOR), document.activeElement);
});

I can't figure out what the last line should be. As of now, it gives me this:

expected null to equal <body class="">

which I don't understand because the BACKDROP_SELECTOR element exists, also why is document.activeElement equals to body after mousing down on the backdrop?

Copy link
Contributor

Choose a reason for hiding this comment

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

✅ test fixed

@blueprint-bot
Copy link

Add test for enforceFocus

Preview: documentation | table
Coverage: core | datetime

@llorca
Copy link
Contributor Author

llorca commented Jul 24, 2017

Made that test work 👍 Ready for review again.

@giladgray giladgray merged commit 794242c into master Jul 28, 2017
@giladgray giladgray deleted the al/dialog-1324 branch July 28, 2017 20:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants