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

Create new useCurrentEuiBreakpoint() utility & provider #6079

Merged
merged 12 commits into from
Jul 27, 2022

Conversation

cee-chen
Copy link
Member

@cee-chen cee-chen commented Jul 26, 2022

Summary

I strongly recommend following along by commit.

What this PR does

This PR DRYs out many repeated window.addEventListener('resize') events across our codebase (which are all creating resize listeners for each instance of each component) in favor of a single resize event listener that returns the current window width as a named EUI breakpoint size (xs through xl).

In order to make this single resize listener possible, a shared context was created and nested within the <EuiProvider> component. bbac89d

Unlike our current breakpoint services / vanilla JS utility fns, this new hook (and now useIsWithinBreakpoints, which dogfoods it) correctly inherits any theme breakpoints override passed to EuiProvider. 🎉

What this PR does NOT do

This PR deliberately avoids breaking changes. As a result, I avoided the following:

  • This PR does NOT touch getBreakpoint, isWithinBreakpoints, isWithinMaxBreakpoint, or isWithinMinBreakpoint to fix/update them to respect theme breakpoints/overrides
  • This PR does NOT DRY out EuiCollapsibleNav or EuiFlyout, as they use isWithinMinBreakpoint

I'm hoping to get more feedback / discussion on how to tackle the above 2 problems and then open up a follow-up PR.

Personally, my strong preference would be to deprecate/remove the 4 exported vanilla JS services completely (possibly in favor of hooks that can call useEuiTheme() to properly get the current theme) and also deprecate the option for them to take static width numbers and take sizes only. Thoughts?

Checklist

  • Checked in mobile
  • Checked in Chrome, Safari, Edge, and Firefox
  • Added documentation
  • Added or updated jest and cypress tests
  • Checked for breaking changes and labeled appropriately
  • A changelog entry exists and is marked appropriately

- [ ] Checked in both light and dark modes
- [ ] Props have proper autodocs and playground toggles
- [ ] Checked Code Sandbox works for any docs examples
- [ ] Checked for accessibility including keyboard-only and screenreader modes
- [ ] Updated the Figma library counterpart

- to allow creating a single provider and splitting up utils
- instead of src/services/hooks

- see src/services/accessibility for another example of a non-generic hook that should live within a specific topic folder
- without a callback, closeMenu reference will be lost and will not be correctly removed
- already declared in our global_styling / themes
…docs

- since those utils do not correct inherit theme overrides, we should likely be deprecating and preferring hooks for future usage
@cee-chen cee-chen requested a review from thompsongl July 26, 2022 23:22
Comment on lines +49 to +51
const onWindowResize = throttle(() => {
setCurrentBreakpoint(getBreakpoint(window.innerWidth, breakpoints));
}, 50);
Copy link
Member Author

@cee-chen cee-chen Jul 26, 2022

Choose a reason for hiding this comment

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

[Perf question] Some of our components used a throttle ms of 50 and some didn't. Since going down to a single (per EuiProvider) resize listener is already more performant than what we had previously, do we have any opinions on whether we need to continue to optimize/throttle this resize listener?

If yay: should we also making this throttle number configurable by consumers, e.g. <EuiProvider breakpointResizeThrottle={0} >? 🤷

Copy link
Contributor

Choose a reason for hiding this comment

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

Let's keep it at 50 for now. I'm sure it was a fairly arbitrary choice that was propagated throughout, but I don't see a reason at the moment to make it configurable.

@@ -41,7 +33,7 @@ export function getBreakpoint(
breakpoints: EuiBreakpoints = BREAKPOINTS
): EuiBreakpointSize | undefined {
// Find the breakpoint (key) whose value is <= windowWidth starting with largest first
return keysOf(BREAKPOINTS).find((key) => breakpoints[key] <= width);
return BREAKPOINT_KEYS.find((key) => breakpoints[key] <= width);
}

/**
Copy link
Member Author

@cee-chen cee-chen Jul 26, 2022

Choose a reason for hiding this comment

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

This PR deliberately avoids breaking changes. As a result, I avoided touching services/breakpoint.ts's getBreakpoint, isWithinBreakpoints, isWithinMaxBreakpoint, or isWithinMinBreakpoint to fix or update them to respect theme breakpoints/overrides.

I'm hoping to get more feedback & discussion on how to tackle the above 2 problems and then open up a follow-up PR.

Personally, my strong preference would be to deprecate/remove the 4 exported vanilla JS services completely (possibly in favor of hooks that can call useEuiTheme() to properly get the current theme), and also deprecate the option for them to take static width numbers and take sizes only. Thoughts?

Copy link
Contributor

Choose a reason for hiding this comment

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

I avoided touching services/breakpoint.ts's getBreakpoint, isWithinBreakpoints, isWithinMaxBreakpoint, or isWithinMinBreakpoint

👍

deprecate/remove the 4 exported vanilla JS services completely

This seems like the right choice. Without access to the current theme variables they present liabilities.
getBreakpoint, isWithinMaxBreakpoint, isWithinMinBreakpointThere are used in Kibana but only to create a useBreakpoints hook, which could simply be replaced with something from EUI.

@cee-chen cee-chen marked this pull request as ready for review July 26, 2022 23:44
@kibanamachine
Copy link

Preview documentation changes for this PR: https://eui.elastic.co/pr_6079/

Copy link
Contributor

@thompsongl thompsongl left a comment

Choose a reason for hiding this comment

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

Nicely done, @constancecchen!

I'm going to run it through some manual testing in Kibana to check on any rerender side effects, but everything else is looking good.

);
};
```
#### A not-recommended, legacy method to consume theming variables from Sass
Copy link
Contributor

Choose a reason for hiding this comment

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

🙇‍♂️

Comment on lines +49 to +51
const onWindowResize = throttle(() => {
setCurrentBreakpoint(getBreakpoint(window.innerWidth, breakpoints));
}, 50);
Copy link
Contributor

Choose a reason for hiding this comment

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

Let's keep it at 50 for now. I'm sure it was a fairly arbitrary choice that was propagated throughout, but I don't see a reason at the moment to make it configurable.

@@ -41,7 +33,7 @@ export function getBreakpoint(
breakpoints: EuiBreakpoints = BREAKPOINTS
): EuiBreakpointSize | undefined {
// Find the breakpoint (key) whose value is <= windowWidth starting with largest first
return keysOf(BREAKPOINTS).find((key) => breakpoints[key] <= width);
return BREAKPOINT_KEYS.find((key) => breakpoints[key] <= width);
}

/**
Copy link
Contributor

Choose a reason for hiding this comment

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

I avoided touching services/breakpoint.ts's getBreakpoint, isWithinBreakpoints, isWithinMaxBreakpoint, or isWithinMinBreakpoint

👍

deprecate/remove the 4 exported vanilla JS services completely

This seems like the right choice. Without access to the current theme variables they present liabilities.
getBreakpoint, isWithinMaxBreakpoint, isWithinMinBreakpointThere are used in Kibana but only to create a useBreakpoints hook, which could simply be replaced with something from EUI.

Copy link
Contributor

@thompsongl thompsongl left a comment

Choose a reason for hiding this comment

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

I'm going to run it through some manual testing in Kibana to check on any rerender side effects

LGTM!

@cee-chen
Copy link
Member Author

Woohoo, thanks Greg!

@cee-chen cee-chen merged commit 85ca5fe into elastic:main Jul 27, 2022
@cee-chen cee-chen deleted the breakpoints branch July 27, 2022 20:16
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.

3 participants