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

[ButtonBase] Use fork of focus-visible polyfill #15484

Merged
merged 9 commits into from
Apr 29, 2019

Conversation

eps1lon
Copy link
Member

@eps1lon eps1lon commented Apr 25, 2019

This is a draft. It doesn't use github drafts to get a netlify deploy.
Prerequisite for #15398

Uses a fork of https://github.com/WICG/focus-visible instead of our own implementation which is quite unresponsive.

Playground:

TODO:

  • prior art? related issues? Edit: Didn't find prior attempts to improve this.
  • Use polyfill as a fallback only
  • cleanup (fork and ButtonBase)
  • probably need to fix tests
  • green build

@ryancogswell You might be interested in this one.

@eps1lon eps1lon added accessibility a11y component: ButtonBase The React component. labels Apr 25, 2019
@mui-pr-bot
Copy link

mui-pr-bot commented Apr 25, 2019

@material-ui/core: parsed: -0.12% 😍, gzip: -0.03% 😍
@material-ui/lab: parsed: -0.39% 😍, gzip: -0.10% 😍

Details of bundle changes.

Comparing: 8c5a1ca...7758875

bundle parsed diff gzip diff prev parsed current parsed prev gzip current gzip
@material-ui/core -0.12% -0.03% 311,394 311,022 84,601 84,579
@material-ui/core/Paper 0.00% -0.01% 67,623 67,623 20,124 20,121
@material-ui/core/Paper.esm 0.00% -0.01% 60,988 60,988 19,020 19,018
@material-ui/core/Popper 0.00% +0.02% 🔺 31,114 31,114 10,803 10,805
@material-ui/core/Textarea 0.00% -0.04% 5,468 5,468 2,365 2,364
@material-ui/core/TrapFocus 0.00% 0.00% 3,731 3,731 1,565 1,565
@material-ui/core/styles/createMuiTheme 0.00% 0.00% 15,943 15,943 5,777 5,777
@material-ui/core/useMediaQuery 0.00% 0.00% 2,106 2,106 974 974
@material-ui/lab -0.39% -0.10% 140,997 140,444 42,651 42,608
@material-ui/styles 0.00% +0.01% 🔺 51,151 51,151 15,148 15,149
@material-ui/system 0.00% 0.00% 11,765 11,765 3,923 3,923
Button -0.74% -0.21% 85,901 85,266 25,732 25,677
Modal 0.00% -0.03% 20,575 20,575 6,603 6,601
colorManipulator 0.00% 0.00% 3,904 3,904 1,543 1,543
docs.landing 0.00% 0.00% 51,486 51,486 11,342 11,342
docs.main -0.02% -0.02% 648,595 648,437 202,362 202,322
packages/material-ui/build/umd/material-ui.production.min.js -0.11% +0.02% 🔺 293,109 292,788 82,525 82,538

Generated by 🚫 dangerJS against 7758875

@ryancogswell
Copy link
Contributor

@eps1lon I verified in this netlify deploy that the Menu focus styling is much more immediate and no longer has the slightly-long-keypress issue I mention as issue 5 here.

packages/material-ui/src/ButtonBase/ButtonBase.js Outdated Show resolved Hide resolved
export function teardown() {
document.removeEventListener('keydown', handleKeyDown, true);
document.removeEventListener('mousedown', handlePointerDown, true);
document.removeEventListener('pointerdown', handlePointerDown, true);
Copy link
Member

Choose a reason for hiding this comment

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

Is the pointerdown event redundant with mousedown and touchstart?

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 haven't really looked into those. Not sure what other pointer types e.g. a pen would trigger in browsers that implement PointerEvents.

Copy link
Member Author

Choose a reason for hiding this comment

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

Keeping it for now until we can verify that a pointerdown from a pen triggers either keydown or mousedown.

handleBlur = createRippleHandler(this, 'Blur', 'stop', () => {
clearTimeout(this.focusVisibleTimeout);
handleBlur = createRippleHandler(this, 'Blur', 'stop', event => {
handleBlur(event);
Copy link
Contributor

Choose a reason for hiding this comment

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

Looking at the WIGC focus-visible.js, I think this handleBlur call should either be moved inside the following if (this.state.focusVisible) { or pass this.state.focusVisible as an additional argument to handleBlur. I don't think hadFocusVisibleRecently = true; should occur unless this element had this.state.focusVisible prior to the blur.

Copy link
Member Author

Choose a reason for hiding this comment

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

Good call. I think we should rename the handleBlur from focusVisible.js to handleBlurVisible. Removing styling etc is the responsibility of the caller but focusVisible.js should manage the global state.

packages/material-ui/src/ButtonBase/ButtonBase.js Outdated Show resolved Hide resolved
enzyme find cant pierce shadow dom
@oliviertassinari
Copy link
Member

oliviertassinari commented Apr 29, 2019

  • We add x listeners for each button base instance. It might be surprising, but I think that it's fine, it probably has no performance implication.
  • If would be great to rebase on the next branch so we can try the menu key feature directly on the preview link.
  • Looks great! I love when a bug fix reduces bundle size. We might want to add a regression test for the menu keyboard feature (I don't know if it's possible) in case we have to change the logic somewhere don't the line.
  • Assuming the focus visible logic will never be used on an element that shows a keyboard, I believe we don't need inputTypesWhitelist. A tooltip can be used to wrap an input ([Tooltip] Display only on keyboard focus #15398). I remember one issue about this use case.

assert.strictEqual(getState().focusVisible, true);
});

it('should ignore the keyboard after 1s', () => {
Copy link
Member

@oliviertassinari oliviertassinari Apr 29, 2019

Choose a reason for hiding this comment

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

We changed the 1s duration at some point, entropy 👋

Copy link
Member Author

Choose a reason for hiding this comment

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

There's alot of behavior that isn't tested right now in our codebase. But this is a fork so it is actually tested somewhere. Just need to make sure we watch for releases of the base.

@eps1lon
Copy link
Member Author

eps1lon commented Apr 29, 2019

Assuming the focus visible logic will never be used on an element that shows a keyboard, I believe we don't need inputTypesWhitelist.

Let's keep it for now and see if the focus visible is useful elsewhere. It's a common a11y helper so I don't want it floating around in the code base under a name that doesn't fully apply.

We add x listeners for each button base instance. It might be surprising, but I think that it's fine, it probably has no performance implication.

It's one listener per document. The only issue is that we don't have automatic cleanup. Unless someone is re-creating documents during app lifetime it should be fine.

@oliviertassinari
Copy link
Member

Let's keep it for now and see if the focus visible is useful elsewhere.

I have edited my comment. It's useful. I remember somebody using a tooltip wrapping an input.

@eps1lon
Copy link
Member Author

eps1lon commented Apr 29, 2019

@ryancogswell Oh my god it's so beautiful (needs 60fps video):
mui-menu-keyboard

@oliviertassinari
Copy link
Member

😍

this.setState({ focusVisible: false });
}
});

componentDidMount() {
listenForFocusKeys(ownerWindow(this.getButtonNode()));

prepareFocusVisible(this.getButtonNode().ownerDocument);
Copy link
Contributor

Choose a reason for hiding this comment

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

@eps1lon It does look like this is going to add a set of document listeners for each ButtonBase mount. Should be able to short-circuit within focusVisible.js prepare function by tracking in a variable whether or not the listeners have already been added to the document.

Copy link
Member

Choose a reason for hiding this comment

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

Should we handle it?

Copy link
Member Author

Choose a reason for hiding this comment

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

It does look like this is going to add a set of document listeners for each ButtonBase mount.

addEventListener does not add duplicate listeners. Unless the focusVisible.js module is recreated for every ButtonBase instance they shouldn't be duplicated.

Copy link
Contributor

Choose a reason for hiding this comment

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

Thanks for the education.

@ryancogswell
Copy link
Contributor

We might want to add a regression test for the menu keyboard feature (I don't know if it's possible) in case we have to change the logic somewhere don't the line.

@oliviertassinari I'll take care of this later this week after this branch is merged. I tried to do this before -- intending to successfully verify it for the arrow keys and then have a failing test for the text navigation, but with the old focusVisible logic I was going to have to do some rather convoluted things to get a successful test for the arrow keys. It should be more straightforward after this branch is merged.

I also noticed an issue with the text navigation for Select when playing with the netlify deploy from this branch. SelectInput has disableListWrap: true. Currently I'm honoring disableListWrap for the text navigation, but I don't think I should. The native select behavior appears to disable wrapping for arrow keys, but wraps for text navigation. I'll address this at the same time as verifying the focusVisible logic in the MenuList tests.

@oliviertassinari
Copy link
Member

@ryancogswell Thanks for the follow-up.

@oliviertassinari oliviertassinari merged commit 6ef44f1 into mui:next Apr 29, 2019
@oliviertassinari
Copy link
Member

@eps1lon People report that Material-UI is slow, this change will greatly help. Really well done 🔥. Thank you for giving a fresh touch at this old logic!

@eps1lon eps1lon deleted the fix/focus-visible branch April 30, 2019 18:57
@eps1lon eps1lon mentioned this pull request May 6, 2019
2 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants