From 378829348cc1311c0c0ee006460d9659b821121f Mon Sep 17 00:00:00 2001 From: Trevor Pierce <1Copenut@users.noreply.github.com> Date: Tue, 20 Sep 2022 08:50:15 -0500 Subject: [PATCH] Bumping EUI to version 64.0.4 (#140323) * Bumping EUI to version 64.0.1. * Updating snapshot tests for two directories. * Deprecate basic usages of getBreakpoint - in favor of useCurrentEuiBreakpoint * [Fleet] Deprecate isWithinMaxBreakpoint - in favor of hook * [DataViz] Update DataVisualizerTable to use window breakpoint vs table resize observer - since getBreakpoint is now deprecated, we're only looking at the current EUI breakpoint (based off window width) * [KibanaThemeProvider] Allow apps to modify the default EUI theme - Setup for custom xl+ breakpoint sizes used by APM and Synthetics * [APM] Update useBreakpoints hook with EUI breakpoint deprecations - since getBreakpoint is no longer an usable util - EUI's new breakpoint hooks already use/debounce window resize events, so we now get to skip all that custom logic by simply making custom EUI breakpoint overrides and using EUI breakpoint hooks - remove returned `breakpoint` and `width` keys - they weren't actually being used anywhere in APM that I could see and were causing type errors. - If someone wants to access them, they can use `useCurrentEuiBreakpoint` and `useWindowSize` individually instead * [UX] Update useBreakpoints hook copied from APM - basically the exact same logic, they just also need the xxl and xxxl breakpoints * [Synthetics] Remove `useBreakpoints` in favor of new EUI breakpoint hooks + add xxl and xxxl breakpoints to Synthetics EUI themes - `useBreakpoints`: - as far as I can tell, all attached APIs are basically the same APIs that EUI provides OOTB: - up -> `useIsWithinMinBreakpoint` - down -> `useIsWithinMaxBreakpoint` - between -> `useIsWithinBreakpoints` - debouncedWidth - not used, but could just use `useWindowSize` directly instead - note: i'm confused by the `xl` override/conflation with `xxl`, but left the default xl breakpoint size as-is and assumed that all usage instances of 'xl' actually wanted 'xxl' * v64.0.2 - add missing backports and several new fixes * v64.0.3 * Fix type error from breakpoint deprecation - functionally doesn't matter since the array doesn't include undefined, so basically just silence TS complaining about it * Updating additional snapshots after bump to EUI 64.0.3 * Adding RUM Jest snapshot update. * Adding Timeout to Fleet token generation test. * Revert "[DataViz] Update DataVisualizerTable to use window breakpoint vs table resize observer" This reverts commit 4e60ce281de1ae58d14664bab172e04dba483d72. * [DataViz] Remove getBreakpoint usage - by replacing the breakpoint logic/switch with custom breakpoint sizes and names - since the table size can be within panels that don't match `window.innerWidth`, we can't use EUI's breakpoint utils here * Restoring a needed hook for breakpoints. * Fix broken side navs on uptime/apm/ux/synthetics - because of their new custom xxl/xxxl breakpoints, the `isLargerBreakpoint` logic was broken on the shared solution nav. switching to a min breakpoint bound fixes the issue and futureproofs the solution nav for all apps that add larger breakpoints than xl * Fix snapshots/unit tests from previous commits * Bumping EUI to 64.0.4 backport. * [PR feedback] Separate DataVisualizerTable more clearly from EUI breakpoints - per discussion with Quynh and Walter, there's some confusion around the breakpoints that the table is using. Since the table is width is not always the width of the browser window, it cannot use EUI's breakpoint hooks, and should instead use its own custom map of table-specific breakpoints to make that separation clearer * [CI] Auto-commit changed files from 'node scripts/precommit_hook.js --ref HEAD~1..HEAD --fix' Co-authored-by: Constance Chen Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- package.json | 2 +- .../__snapshots__/solution_nav.test.tsx.snap | 554 ++++++++++++++++-- .../page/solution_nav/src/solution_nav.tsx | 3 +- .../solution_nav/src/with_solution_nav.tsx | 9 +- src/dev/license_checker/config.ts | 2 +- .../public/theme/kibana_theme_provider.tsx | 6 +- .../public/theme/kibana_theme_provider.tsx | 6 +- .../public/theme/kibana_theme_provider.tsx | 6 +- .../plugins/apm/public/application/index.tsx | 10 +- .../apm/public/hooks/use_breakpoints.test.ts | 153 ----- .../apm/public/hooks/use_breakpoints.test.tsx | 125 ++++ .../apm/public/hooks/use_breakpoints.ts | 45 +- .../var_config.stories.storyshot | 1 + .../filters_group.component.stories.storyshot | 2 + ...orkpad_filters.component.stories.storyshot | 5 + .../data_visualizer_stats_table.tsx | 2 +- .../common/components/stats_table/utils.ts | 60 +- .../fleet/cypress/e2e/enrollment_token.cy.ts | 4 +- .../add_first_integration_splash.tsx | 6 +- .../components/nodes_overview.tsx | 6 +- .../solution_grouped_nav_panel.test.tsx | 8 +- .../solution_grouped_nav_panel.tsx | 4 +- .../pages/synthetics_page_template.test.tsx | 10 +- .../common/pages/synthetics_page_template.tsx | 6 +- .../monitor_list_table/monitor_list.tsx | 4 +- .../public/apps/synthetics/hooks/index.ts | 1 - .../public/apps/synthetics/synthetics_app.tsx | 10 +- .../public/hooks/use_breakpoints.test.ts | 96 --- .../public/hooks/use_breakpoints.ts | 114 ---- .../public/legacy_uptime/app/uptime_app.tsx | 10 +- .../app/uptime_page_template.test.tsx | 10 +- .../app/uptime_page_template.tsx | 6 +- .../ping_timestamp/step_image_caption.tsx | 14 +- .../monitor_list/monitor_list.tsx | 4 +- .../overview/monitor_list/monitor_list.tsx | 11 +- .../pages/synthetics/checks_navigation.tsx | 13 +- .../plugins/ux/public/application/ux_app.tsx | 10 +- .../ux/public/hooks/use_breakpoints.ts | 45 +- yarn.lock | 8 +- 39 files changed, 814 insertions(+), 577 deletions(-) delete mode 100644 x-pack/plugins/apm/public/hooks/use_breakpoints.test.ts create mode 100644 x-pack/plugins/apm/public/hooks/use_breakpoints.test.tsx delete mode 100644 x-pack/plugins/synthetics/public/hooks/use_breakpoints.test.ts delete mode 100644 x-pack/plugins/synthetics/public/hooks/use_breakpoints.ts diff --git a/package.json b/package.json index b6412ba7779db7..d895c8d00e8198 100644 --- a/package.json +++ b/package.json @@ -109,7 +109,7 @@ "@elastic/datemath": "5.0.3", "@elastic/elasticsearch": "npm:@elastic/elasticsearch-canary@8.3.0-canary.1", "@elastic/ems-client": "8.3.3", - "@elastic/eui": "63.0.6", + "@elastic/eui": "64.0.4", "@elastic/filesaver": "1.1.2", "@elastic/node-crypto": "1.2.1", "@elastic/numeral": "^2.5.1", diff --git a/packages/shared-ux/page/solution_nav/src/__snapshots__/solution_nav.test.tsx.snap b/packages/shared-ux/page/solution_nav/src/__snapshots__/solution_nav.test.tsx.snap index 466d3bcf0dea69..1db22e47d0c52a 100644 --- a/packages/shared-ux/page/solution_nav/src/__snapshots__/solution_nav.test.tsx.snap +++ b/packages/shared-ux/page/solution_nav/src/__snapshots__/solution_nav.test.tsx.snap @@ -4,7 +4,7 @@ exports[`SolutionNav accepts EuiSideNavProps 1`] = ` +
+ +

+ + + +

+
+ + +
+
`; @@ -104,7 +193,7 @@ exports[`SolutionNav accepts canBeCollapsed prop 1`] = ` +
+ +

+ + + +

+
+ + +
+
`; @@ -295,6 +472,91 @@ exports[`SolutionNav accepts canBeCollapsed prop 2`] = ` /> +
+ +

+ + + +

+
+ + +
`; @@ -302,7 +564,7 @@ exports[`SolutionNav heading accepts more headingProps 1`] = ` +
+ +

+ + + +

+
+ +
+
`; @@ -341,7 +632,7 @@ exports[`SolutionNav renders 1`] = ` +
+ +

+ + + +

+
+ + +
+
`; @@ -440,7 +819,7 @@ exports[`SolutionNav renders with icon 1`] = ` +
+ +

+ + + + +

+
+ + +
+
`; diff --git a/packages/shared-ux/page/solution_nav/src/solution_nav.tsx b/packages/shared-ux/page/solution_nav/src/solution_nav.tsx index 31950f716c225f..d6b9a2063e609f 100644 --- a/packages/shared-ux/page/solution_nav/src/solution_nav.tsx +++ b/packages/shared-ux/page/solution_nav/src/solution_nav.tsx @@ -22,6 +22,7 @@ import { EuiTitle, htmlIdGenerator, useIsWithinBreakpoints, + useIsWithinMinBreakpoint, } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n-react'; import { i18n } from '@kbn/i18n'; @@ -100,7 +101,7 @@ export const SolutionNav: FC = ({ }) => { const isSmallerBreakpoint = useIsWithinBreakpoints(mobileBreakpoints); const isMediumBreakpoint = useIsWithinBreakpoints(['m']); - const isLargerBreakpoint = useIsWithinBreakpoints(['l', 'xl']); + const isLargerBreakpoint = useIsWithinMinBreakpoint('l'); // This is used for both the `EuiSideNav` and `EuiFlyout` toggling const [isSideNavOpenOnMobile, setIsSideNavOpenOnMobile] = useState(false); diff --git a/packages/shared-ux/page/solution_nav/src/with_solution_nav.tsx b/packages/shared-ux/page/solution_nav/src/with_solution_nav.tsx index ef94ed89ac8737..a618f6d6ba41c2 100644 --- a/packages/shared-ux/page/solution_nav/src/with_solution_nav.tsx +++ b/packages/shared-ux/page/solution_nav/src/with_solution_nav.tsx @@ -8,7 +8,12 @@ import React, { ComponentType, ReactNode, useState } from 'react'; import classNames from 'classnames'; -import { useIsWithinBreakpoints, useEuiTheme, EuiPageSidebarProps } from '@elastic/eui'; +import { + useIsWithinBreakpoints, + useEuiTheme, + useIsWithinMinBreakpoint, + EuiPageSidebarProps, +} from '@elastic/eui'; import { SolutionNav, SolutionNavProps } from './solution_nav'; import './with_solution_nav.scss'; @@ -35,7 +40,7 @@ const SOLUTION_NAV_COLLAPSED_KEY = 'solutionNavIsCollapsed'; export const withSolutionNav =

(WrappedComponent: ComponentType

) => { const WithSolutionNav = (props: Props

) => { const isMediumBreakpoint = useIsWithinBreakpoints(['m']); - const isLargerBreakpoint = useIsWithinBreakpoints(['l', 'xl']); + const isLargerBreakpoint = useIsWithinMinBreakpoint('l'); const [isSideNavOpenOnDesktop, setisSideNavOpenOnDesktop] = useState( !JSON.parse(String(localStorage.getItem(SOLUTION_NAV_COLLAPSED_KEY))) ); diff --git a/src/dev/license_checker/config.ts b/src/dev/license_checker/config.ts index fb7416baf0d032..840d7564681a89 100644 --- a/src/dev/license_checker/config.ts +++ b/src/dev/license_checker/config.ts @@ -84,6 +84,6 @@ export const LICENSE_OVERRIDES = { 'jsts@1.6.2': ['Eclipse Distribution License - v 1.0'], // cf. https://github.com/bjornharrtell/jsts '@mapbox/jsonlint-lines-primitives@2.0.2': ['MIT'], // license in readme https://github.com/tmcw/jsonlint '@elastic/ems-client@8.3.3': ['Elastic License 2.0'], - '@elastic/eui@63.0.6': ['SSPL-1.0 OR Elastic License 2.0'], + '@elastic/eui@64.0.4': ['SSPL-1.0 OR Elastic License 2.0'], 'language-subtag-registry@0.3.21': ['CC-BY-4.0'], // retired ODC‑By license https://github.com/mattcg/language-subtag-registry }; diff --git a/src/plugins/interactive_setup/public/theme/kibana_theme_provider.tsx b/src/plugins/interactive_setup/public/theme/kibana_theme_provider.tsx index 9ac4fa6bccd10b..58bf763a60b16b 100644 --- a/src/plugins/interactive_setup/public/theme/kibana_theme_provider.tsx +++ b/src/plugins/interactive_setup/public/theme/kibana_theme_provider.tsx @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { EuiProvider } from '@elastic/eui'; +import { EuiProvider, EuiProviderProps } from '@elastic/eui'; import createCache from '@emotion/cache'; import type { FC } from 'react'; import React, { useMemo } from 'react'; @@ -19,6 +19,7 @@ import { getColorMode } from './utils'; interface KibanaThemeProviderProps { theme$: Observable; + modify?: EuiProviderProps<{}>['modify']; } const defaultTheme: CoreTheme = { @@ -38,7 +39,7 @@ emotionCache.compat = true; /** * Copied from the `kibana_react` plugin, remove once https://github.com/elastic/kibana/issues/119204 is implemented. */ -export const KibanaThemeProvider: FC = ({ theme$, children }) => { +export const KibanaThemeProvider: FC = ({ theme$, modify, children }) => { const theme = useObservable(theme$, defaultTheme); const colorMode = useMemo(() => getColorMode(theme), [theme]); return ( @@ -47,6 +48,7 @@ export const KibanaThemeProvider: FC = ({ theme$, chil cache={{ default: emotionCache, global: globalCache }} globalStyles={false} utilityClasses={false} + modify={modify} > {children} diff --git a/src/plugins/kibana_react/public/theme/kibana_theme_provider.tsx b/src/plugins/kibana_react/public/theme/kibana_theme_provider.tsx index 52fd1e49eb6487..b5715d3f57b623 100644 --- a/src/plugins/kibana_react/public/theme/kibana_theme_provider.tsx +++ b/src/plugins/kibana_react/public/theme/kibana_theme_provider.tsx @@ -9,13 +9,14 @@ import React, { FC, useMemo } from 'react'; import useObservable from 'react-use/lib/useObservable'; import { Observable } from 'rxjs'; -import { EuiProvider } from '@elastic/eui'; +import { EuiProvider, EuiProviderProps } from '@elastic/eui'; import createCache from '@emotion/cache'; import type { CoreTheme } from '@kbn/core/public'; import { getColorMode } from './utils'; interface KibanaThemeProviderProps { theme$: Observable; + modify?: EuiProviderProps<{}>['modify']; } const defaultTheme: CoreTheme = { @@ -36,7 +37,7 @@ emotionCache.compat = true; That copy and this comment can be removed once https://github.com/elastic/kibana/issues/119204 is implemented.*/ // IMPORTANT: This code has been copied to the `kibana_utils` plugin, to avoid cyclical dependency, any changes here should be applied there too. -export const KibanaThemeProvider: FC = ({ theme$, children }) => { +export const KibanaThemeProvider: FC = ({ theme$, modify, children }) => { const theme = useObservable(theme$, defaultTheme); const colorMode = useMemo(() => getColorMode(theme), [theme]); return ( @@ -45,6 +46,7 @@ export const KibanaThemeProvider: FC = ({ theme$, chil cache={{ default: emotionCache, global: globalCache }} globalStyles={false} utilityClasses={false} + modify={modify} > {children} diff --git a/src/plugins/kibana_utils/public/theme/kibana_theme_provider.tsx b/src/plugins/kibana_utils/public/theme/kibana_theme_provider.tsx index 68690b57c8283a..92434d412c84cd 100644 --- a/src/plugins/kibana_utils/public/theme/kibana_theme_provider.tsx +++ b/src/plugins/kibana_utils/public/theme/kibana_theme_provider.tsx @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { EuiProvider } from '@elastic/eui'; +import { EuiProvider, EuiProviderProps } from '@elastic/eui'; import createCache from '@emotion/cache'; import type { FC } from 'react'; import React, { useMemo } from 'react'; @@ -18,6 +18,7 @@ import { getColorMode } from './utils'; interface KibanaThemeProviderProps { theme$: Observable; + modify?: EuiProviderProps<{}>['modify']; } const defaultTheme: CoreTheme = { @@ -37,7 +38,7 @@ emotionCache.compat = true; /** * Copied from the `kibana_react` plugin, to avoid cyclical dependency */ -export const KibanaThemeProvider: FC = ({ theme$, children }) => { +export const KibanaThemeProvider: FC = ({ theme$, modify, children }) => { const theme = useObservable(theme$, defaultTheme); const colorMode = useMemo(() => getColorMode(theme), [theme]); return ( @@ -46,6 +47,7 @@ export const KibanaThemeProvider: FC = ({ theme$, chil cache={{ default: emotionCache, global: globalCache }} globalStyles={false} utilityClasses={false} + modify={modify} > {children} diff --git a/x-pack/plugins/apm/public/application/index.tsx b/x-pack/plugins/apm/public/application/index.tsx index 1fff65f4746ad6..c3cf929a402092 100644 --- a/x-pack/plugins/apm/public/application/index.tsx +++ b/x-pack/plugins/apm/public/application/index.tsx @@ -64,7 +64,15 @@ export const renderApp = ({ element.classList.add(APP_WRAPPER_CLASS); ReactDOM.render( - + { - describe('getScreenSizes', () => { - it('return xs when within 0px - 5740x', () => { - expect(getScreenSizes(0)).toEqual({ - isXSmall: true, - isSmall: true, - isMedium: true, - isLarge: true, - isXl: true, - isXXL: true, - isXXXL: false, - }); - expect(getScreenSizes(574)).toEqual({ - isXSmall: true, - isSmall: true, - isMedium: true, - isLarge: true, - isXl: true, - isXXL: true, - isXXXL: false, - }); - }); - it('return s when within 575px - 767px', () => { - expect(getScreenSizes(575)).toEqual({ - isXSmall: false, - isSmall: true, - isMedium: true, - isLarge: true, - isXl: true, - isXXL: true, - isXXXL: false, - }); - expect(getScreenSizes(767)).toEqual({ - isXSmall: false, - isSmall: true, - isMedium: true, - isLarge: true, - isXl: true, - isXXL: true, - isXXXL: false, - }); - }); - it('return m when within 768px - 991', () => { - expect(getScreenSizes(768)).toEqual({ - isXSmall: false, - isSmall: false, - isMedium: true, - isLarge: true, - isXl: true, - isXXL: true, - isXXXL: false, - }); - expect(getScreenSizes(991)).toEqual({ - isXSmall: false, - isSmall: false, - isMedium: true, - isLarge: true, - isXl: true, - isXXL: true, - isXXXL: false, - }); - }); - it('return l when within 992px - 1199px', () => { - expect(getScreenSizes(992)).toEqual({ - isXSmall: false, - isSmall: false, - isMedium: false, - isLarge: true, - isXl: true, - isXXL: true, - isXXXL: false, - }); - expect(getScreenSizes(1199)).toEqual({ - isXSmall: false, - isSmall: false, - isMedium: false, - isLarge: true, - isXl: true, - isXXL: true, - isXXXL: false, - }); - }); - it('return xl when within 1200px - 1599px', () => { - expect(getScreenSizes(1200)).toEqual({ - isXSmall: false, - isSmall: false, - isMedium: false, - isLarge: false, - isXl: true, - isXXL: true, - isXXXL: false, - }); - expect(getScreenSizes(1599)).toEqual({ - isXSmall: false, - isSmall: false, - isMedium: false, - isLarge: false, - isXl: true, - isXXL: true, - isXXXL: false, - }); - }); - it('return xxl when within 1600px - 1999px', () => { - expect(getScreenSizes(1600)).toEqual({ - isXSmall: false, - isSmall: false, - isMedium: false, - isLarge: false, - isXl: false, - isXXL: true, - isXXXL: false, - }); - expect(getScreenSizes(1999)).toEqual({ - isXSmall: false, - isSmall: false, - isMedium: false, - isLarge: false, - isXl: false, - isXXL: true, - isXXXL: false, - }); - }); - it('return xxxl when greater than or equals to 2000px', () => { - expect(getScreenSizes(2000)).toEqual({ - isXSmall: false, - isSmall: false, - isMedium: false, - isLarge: false, - isXl: false, - isXXL: false, - isXXXL: true, - }); - expect(getScreenSizes(3000)).toEqual({ - isXSmall: false, - isSmall: false, - isMedium: false, - isLarge: false, - isXl: false, - isXXL: false, - isXXXL: true, - }); - }); - }); -}); diff --git a/x-pack/plugins/apm/public/hooks/use_breakpoints.test.tsx b/x-pack/plugins/apm/public/hooks/use_breakpoints.test.tsx new file mode 100644 index 00000000000000..7af7f258447edf --- /dev/null +++ b/x-pack/plugins/apm/public/hooks/use_breakpoints.test.tsx @@ -0,0 +1,125 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { FC } from 'react'; +import { renderHook } from '@testing-library/react-hooks'; +import { EuiProvider } from '@elastic/eui'; +import { useBreakpoints } from './use_breakpoints'; + +const wrapper: FC = ({ children }) => ( + + {children} + +); + +describe('useBreakpoints', () => { + test('xs breakpoint', () => { + window.innerWidth = 0; + const { result } = renderHook(() => useBreakpoints(), { wrapper }); + expect(result.current).toEqual({ + isXSmall: true, + isSmall: true, + isMedium: true, + isLarge: true, + isXl: true, + isXXL: true, + isXXXL: false, + }); + }); + + test('s breakpoint', () => { + window.innerWidth = 575; + const { result } = renderHook(() => useBreakpoints(), { wrapper }); + expect(result.current).toEqual({ + isXSmall: false, + isSmall: true, + isMedium: true, + isLarge: true, + isXl: true, + isXXL: true, + isXXXL: false, + }); + }); + + test('m breakpoint', () => { + window.innerWidth = 768; + const { result } = renderHook(() => useBreakpoints(), { wrapper }); + expect(result.current).toEqual({ + isXSmall: false, + isSmall: false, + isMedium: true, + isLarge: true, + isXl: true, + isXXL: true, + isXXXL: false, + }); + }); + + test('l breakpoint', () => { + window.innerWidth = 992; + const { result } = renderHook(() => useBreakpoints(), { wrapper }); + expect(result.current).toEqual({ + isXSmall: false, + isSmall: false, + isMedium: false, + isLarge: true, + isXl: true, + isXXL: true, + isXXXL: false, + }); + }); + + test('xl breakpoint', () => { + window.innerWidth = 1200; + const { result } = renderHook(() => useBreakpoints(), { wrapper }); + expect(result.current).toEqual({ + isXSmall: false, + isSmall: false, + isMedium: false, + isLarge: false, + isXl: true, + isXXL: true, + isXXXL: false, + }); + }); + + test('xxl breakpoint', () => { + window.innerWidth = 1600; + const { result } = renderHook(() => useBreakpoints(), { wrapper }); + expect(result.current).toEqual({ + isXSmall: false, + isSmall: false, + isMedium: false, + isLarge: false, + isXl: false, + isXXL: true, + isXXXL: false, + }); + }); + + test('xxxl breakpoint', () => { + window.innerWidth = 2000; + const { result } = renderHook(() => useBreakpoints(), { wrapper }); + expect(result.current).toEqual({ + isXSmall: false, + isSmall: false, + isMedium: false, + isLarge: false, + isXl: false, + isXXL: false, + isXXXL: true, + }); + }); +}); diff --git a/x-pack/plugins/apm/public/hooks/use_breakpoints.ts b/x-pack/plugins/apm/public/hooks/use_breakpoints.ts index f87ddb929b66a2..9ec8b20bb472d7 100644 --- a/x-pack/plugins/apm/public/hooks/use_breakpoints.ts +++ b/x-pack/plugins/apm/public/hooks/use_breakpoints.ts @@ -5,42 +5,23 @@ * 2.0. */ -import { useState } from 'react'; -import useWindowSize from 'react-use/lib/useWindowSize'; -import useDebounce from 'react-use/lib/useDebounce'; import { - getBreakpoint, - isWithinMaxBreakpoint, - isWithinMinBreakpoint, + useIsWithinMaxBreakpoint, + useIsWithinMinBreakpoint, } from '@elastic/eui'; -export type Breakpoints = ReturnType; - -export function getScreenSizes(windowWidth: number) { - return { - isXSmall: isWithinMaxBreakpoint(windowWidth, 'xs'), - isSmall: isWithinMaxBreakpoint(windowWidth, 's'), - isMedium: isWithinMaxBreakpoint(windowWidth, 'm'), - isLarge: isWithinMaxBreakpoint(windowWidth, 'l'), - isXl: isWithinMaxBreakpoint(windowWidth, 1599), - isXXL: isWithinMaxBreakpoint(windowWidth, 1999), - isXXXL: isWithinMinBreakpoint(windowWidth, 2000), - }; -} +export type Breakpoints = Record; export function useBreakpoints() { - const { width } = useWindowSize(); - const [breakpoint, setBreakpoint] = useState(getBreakpoint(width)); - const [screenSizes, setScreenSizes] = useState(getScreenSizes(width)); - - useDebounce( - () => { - setBreakpoint(getBreakpoint(width)); - setScreenSizes(getScreenSizes(width)); - }, - 50, - [width] - ); + const screenSizes = { + isXSmall: useIsWithinMaxBreakpoint('xs'), + isSmall: useIsWithinMaxBreakpoint('s'), + isMedium: useIsWithinMaxBreakpoint('m'), + isLarge: useIsWithinMaxBreakpoint('l'), + isXl: useIsWithinMaxBreakpoint('xl'), + isXXL: useIsWithinMaxBreakpoint('xxl'), + isXXXL: useIsWithinMinBreakpoint('xxxl'), + }; - return { ...screenSizes, breakpoint, width }; + return screenSizes; } diff --git a/x-pack/plugins/canvas/public/components/var_config/__stories__/__snapshots__/var_config.stories.storyshot b/x-pack/plugins/canvas/public/components/var_config/__stories__/__snapshots__/var_config.stories.storyshot index 208d358405f191..ea557ae50328fd 100644 --- a/x-pack/plugins/canvas/public/components/var_config/__stories__/__snapshots__/var_config.stories.storyshot +++ b/x-pack/plugins/canvas/public/components/var_config/__stories__/__snapshots__/var_config.stories.storyshot @@ -36,6 +36,7 @@ exports[`Storyshots components/Variables/VarConfig default 1`] = ` aria-controls="accordion-variables" aria-expanded={false} className="euiAccordion__button emotion-euiAccordion__button" + disabled={false} id="generated-id" onClick={[Function]} type="button" diff --git a/x-pack/plugins/canvas/public/components/workpad_filters/__stories__/__snapshots__/filters_group.component.stories.storyshot b/x-pack/plugins/canvas/public/components/workpad_filters/__stories__/__snapshots__/filters_group.component.stories.storyshot index cc3140aa50c1e5..daf25ece5607a5 100644 --- a/x-pack/plugins/canvas/public/components/workpad_filters/__stories__/__snapshots__/filters_group.component.stories.storyshot +++ b/x-pack/plugins/canvas/public/components/workpad_filters/__stories__/__snapshots__/filters_group.component.stories.storyshot @@ -41,6 +41,7 @@ exports[`Storyshots components/WorkpadFilters/FiltersGroupComponent default 1`] aria-controls="canvas-filter-group-0" aria-expanded={true} className="euiAccordion__button emotion-euiAccordion__button" + disabled={false} id="generated-id" onClick={[Function]} type="button" @@ -696,6 +697,7 @@ exports[`Storyshots components/WorkpadFilters/FiltersGroupComponent empty group aria-controls="canvas-filter-group-0" aria-expanded={true} className="euiAccordion__button emotion-euiAccordion__button" + disabled={false} id="generated-id" onClick={[Function]} type="button" diff --git a/x-pack/plugins/canvas/public/components/workpad_filters/__stories__/__snapshots__/workpad_filters.component.stories.storyshot b/x-pack/plugins/canvas/public/components/workpad_filters/__stories__/__snapshots__/workpad_filters.component.stories.storyshot index 7cc8edb5e69c96..86d0fd0a46c22b 100644 --- a/x-pack/plugins/canvas/public/components/workpad_filters/__stories__/__snapshots__/workpad_filters.component.stories.storyshot +++ b/x-pack/plugins/canvas/public/components/workpad_filters/__stories__/__snapshots__/workpad_filters.component.stories.storyshot @@ -206,6 +206,7 @@ exports[`Storyshots components/WorkpadFilters/WorkpadFiltersComponent Filters gr aria-controls="canvas-filter-group-0" aria-expanded={true} className="euiAccordion__button emotion-euiAccordion__button" + disabled={false} id="generated-id" onClick={[Function]} type="button" @@ -941,6 +942,7 @@ exports[`Storyshots components/WorkpadFilters/WorkpadFiltersComponent Filters gr aria-controls="canvas-filter-group-0" aria-expanded={true} className="euiAccordion__button emotion-euiAccordion__button" + disabled={false} id="generated-id" onClick={[Function]} type="button" @@ -1676,6 +1678,7 @@ exports[`Storyshots components/WorkpadFilters/WorkpadFiltersComponent Filters gr aria-controls="canvas-filter-group-0" aria-expanded={true} className="euiAccordion__button emotion-euiAccordion__button" + disabled={false} id="generated-id" onClick={[Function]} type="button" @@ -1834,6 +1837,7 @@ exports[`Storyshots components/WorkpadFilters/WorkpadFiltersComponent default 1` aria-controls="canvas-filter-group-0" aria-expanded={true} className="euiAccordion__button emotion-euiAccordion__button" + disabled={false} id="generated-id" onClick={[Function]} type="button" @@ -2194,6 +2198,7 @@ exports[`Storyshots components/WorkpadFilters/WorkpadFiltersComponent default 1` aria-controls="canvas-filter-group-1" aria-expanded={true} className="euiAccordion__button emotion-euiAccordion__button" + disabled={false} id="generated-id" onClick={[Function]} type="button" diff --git a/x-pack/plugins/data_visualizer/public/application/common/components/stats_table/data_visualizer_stats_table.tsx b/x-pack/plugins/data_visualizer/public/application/common/components/stats_table/data_visualizer_stats_table.tsx index 63caec538ea5e4..a0006431d9d722 100644 --- a/x-pack/plugins/data_visualizer/public/application/common/components/stats_table/data_visualizer_stats_table.tsx +++ b/x-pack/plugins/data_visualizer/public/application/common/components/stats_table/data_visualizer_stats_table.tsx @@ -134,7 +134,7 @@ export const DataVisualizerTable = ({ const columns = useMemo(() => { const expanderColumn: EuiTableComputedColumnType = { name: - dimensions.breakPoint !== 'xs' && dimensions.breakPoint !== 's' ? ( + dimensions.breakPoint !== 'small' ? ( { @@ -38,6 +37,13 @@ export const getTFPercentage = (config: FileBasedFieldVisConfig) => { }; }; +// Map of DataVisualizerTable breakpoints specific to the table component +// Note that the table width is not always the full width of the browser window +const TABLE_BREAKPOINTS = { + small: 600, + medium: 1000, + large: Infinity, // default +}; export const calculateTableColumnsDimensions = (width?: number) => { const defaultSettings = { expander: '40px', @@ -46,36 +52,30 @@ export const calculateTableColumnsDimensions = (width?: number) => { distinctValues: '225px', distributions: '225px', showIcon: true, - breakPoint: 'xl', + breakPoint: 'large', }; if (width === undefined) return defaultSettings; - const breakPoint = getBreakpoint(width); - switch (breakPoint) { - case 'xs': - case 's': - return { - expander: '25px', - type: '40px', - docCount: 'auto', - distinctValues: 'auto', - distributions: 'auto', - showIcon: false, - breakPoint, - }; - - case 'm': - case 'l': - return { - expander: '25px', - type: '40px', - docCount: 'auto', - distinctValues: 'auto', - distributions: 'auto', - showIcon: false, - breakPoint, - }; - - default: - return defaultSettings; + if (width <= TABLE_BREAKPOINTS.small) { + return { + expander: '25px', + type: '40px', + docCount: 'auto', + distinctValues: 'auto', + distributions: 'auto', + showIcon: false, + breakPoint: 'small', + }; + } + if (width <= TABLE_BREAKPOINTS.medium) { + return { + expander: '25px', + type: '40px', + docCount: 'auto', + distinctValues: 'auto', + distributions: 'auto', + showIcon: false, + breakPoint: 'medium', + }; } + return defaultSettings; }; diff --git a/x-pack/plugins/fleet/cypress/e2e/enrollment_token.cy.ts b/x-pack/plugins/fleet/cypress/e2e/enrollment_token.cy.ts index e60842a2992672..88c94815eee0dc 100644 --- a/x-pack/plugins/fleet/cypress/e2e/enrollment_token.cy.ts +++ b/x-pack/plugins/fleet/cypress/e2e/enrollment_token.cy.ts @@ -24,7 +24,9 @@ describe('Enrollment token page', () => { }, headers: { 'kbn-xsrf': 'cypress' }, }); - cy.getBySel(ENROLLMENT_TOKENS_TAB).click(); + cy.getBySel(ENROLLMENT_TOKENS_TAB, { + timeout: 15000, + }).click(); }); after(() => { diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/multi_page_layout/components/add_first_integration_splash.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/multi_page_layout/components/add_first_integration_splash.tsx index bc265c11b18c6a..1e0aeb32364925 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/multi_page_layout/components/add_first_integration_splash.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/multi_page_layout/components/add_first_integration_splash.tsx @@ -6,7 +6,6 @@ */ import React from 'react'; import styled from 'styled-components'; -import useWindowSize from 'react-use/lib/useWindowSize'; import { FormattedMessage } from '@kbn/i18n-react'; import type { EuiImageProps } from '@elastic/eui'; @@ -22,7 +21,7 @@ import { EuiLink, EuiHideFor, EuiShowFor, - isWithinMaxBreakpoint, + useIsWithinMaxBreakpoint, } from '@elastic/eui'; import type { RegistryPolicyTemplate, PackageInfo } from '../../../../../types'; @@ -66,8 +65,7 @@ const CenteredEuiImage = (props: EuiImageProps) => ( ); const ResponsiveStepGroup: React.FC = ({ children }) => { - const { width } = useWindowSize(); - const isScreenSmall = isWithinMaxBreakpoint(width, 's'); + const isScreenSmall = useIsWithinMaxBreakpoint('s'); return ( { + const currentBreakpoint = useCurrentEuiBreakpoint(); + const handleDrilldown = useCallback( (filter: string) => { onDrilldown({ @@ -102,7 +104,7 @@ export const NodesOverview = ({ } const dataBounds = calculateBoundsFromNodes(nodes); const bounds = autoBounds ? dataBounds : boundsOverride; - const isStatic = ['xs', 's'].includes(getBreakpoint(window.innerWidth)!); + const isStatic = ['xs', 's'].includes(currentBreakpoint!); if (view === 'table') { return ( diff --git a/x-pack/plugins/security_solution/public/common/components/navigation/solution_grouped_nav/solution_grouped_nav_panel.test.tsx b/x-pack/plugins/security_solution/public/common/components/navigation/solution_grouped_nav/solution_grouped_nav_panel.test.tsx index 6b99a68c043aac..3ff29d0f693e18 100644 --- a/x-pack/plugins/security_solution/public/common/components/navigation/solution_grouped_nav/solution_grouped_nav_panel.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/navigation/solution_grouped_nav/solution_grouped_nav_panel.test.tsx @@ -16,12 +16,12 @@ import type { DefaultSideNavItem } from './types'; import { bottomNavOffset } from '../../../lib/helpers'; import { BETA } from '@kbn/kubernetes-security-plugin/common/translations'; -const mockUseIsWithinBreakpoints = jest.fn(() => true); +const mockUseIsWithinMinBreakpoint = jest.fn(() => true); jest.mock('@elastic/eui', () => { const original = jest.requireActual('@elastic/eui'); return { ...original, - useIsWithinBreakpoints: () => mockUseIsWithinBreakpoints(), + useIsWithinMinBreakpoint: () => mockUseIsWithinMinBreakpoint(), }; }); @@ -143,14 +143,14 @@ describe('SolutionGroupedNav', () => { describe('bottom offset', () => { it('should add bottom offset', () => { - mockUseIsWithinBreakpoints.mockReturnValueOnce(true); + mockUseIsWithinMinBreakpoint.mockReturnValueOnce(true); const result = renderNavPanel({ bottomOffset: bottomNavOffset }); expect(result.getByTestId('groupedNavPanel')).toHaveStyle({ bottom: bottomNavOffset }); }); it('should not add bottom offset if not large screen', () => { - mockUseIsWithinBreakpoints.mockReturnValueOnce(false); + mockUseIsWithinMinBreakpoint.mockReturnValueOnce(false); const result = renderNavPanel({ bottomOffset: bottomNavOffset }); expect(result.getByTestId('groupedNavPanel')).not.toHaveStyle({ bottom: bottomNavOffset }); diff --git a/x-pack/plugins/security_solution/public/common/components/navigation/solution_grouped_nav/solution_grouped_nav_panel.tsx b/x-pack/plugins/security_solution/public/common/components/navigation/solution_grouped_nav/solution_grouped_nav_panel.tsx index 2c7dbf4074983d..cf38f0c60ebfa6 100644 --- a/x-pack/plugins/security_solution/public/common/components/navigation/solution_grouped_nav/solution_grouped_nav_panel.tsx +++ b/x-pack/plugins/security_solution/public/common/components/navigation/solution_grouped_nav/solution_grouped_nav_panel.tsx @@ -20,7 +20,7 @@ import { EuiTitle, EuiWindowEvent, keys, - useIsWithinBreakpoints, + useIsWithinMinBreakpoint, } from '@elastic/eui'; import classNames from 'classnames'; import { EuiPanelStyled, FlexLink } from './solution_grouped_nav_panel.styles'; @@ -57,7 +57,7 @@ const SolutionNavPanelComponent: React.FC = ({ items, bottomOffset, }) => { - const isLargerBreakpoint = useIsWithinBreakpoints(['l', 'xl']); + const isLargerBreakpoint = useIsWithinMinBreakpoint('l'); const panelClasses = classNames('eui-yScroll'); // Only larger breakpoint needs to add bottom offset, other sizes should have full height diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/common/pages/synthetics_page_template.test.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/common/pages/synthetics_page_template.test.tsx index bd58aa12b1c821..e7b166fe7b5fae 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/common/pages/synthetics_page_template.test.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/common/pages/synthetics_page_template.test.tsx @@ -11,14 +11,6 @@ import 'jest-styled-components'; import { render } from '../../../utils/testing/rtl_helpers'; import { SyntheticsPageTemplateComponent } from './synthetics_page_template'; import { OVERVIEW_ROUTE } from '../../../../../../common/constants'; -import { useBreakpoints } from '../../../../../hooks/use_breakpoints'; - -jest.mock('../../../../../hooks/use_breakpoints', () => { - const down = jest.fn().mockReturnValue(false); - return { - useBreakpoints: () => ({ down }), - }; -}); describe('SyntheticsPageTemplateComponent', () => { describe('styling', () => { @@ -34,7 +26,7 @@ describe('SyntheticsPageTemplateComponent', () => { }); it('applies the header centering on mobile', () => { - (useBreakpoints().down as jest.Mock).mockReturnValue(true); + window.innerWidth = 600; const { container } = render(); expect(container.firstChild).toBeDefined(); }); diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/common/pages/synthetics_page_template.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/common/pages/synthetics_page_template.tsx index 657ad3cb2391cd..dcd139727a1388 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/common/pages/synthetics_page_template.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/common/pages/synthetics_page_template.tsx @@ -7,14 +7,13 @@ import React, { useEffect, useMemo } from 'react'; import styled from 'styled-components'; -import { EuiPageHeaderProps, EuiPageTemplateProps } from '@elastic/eui'; +import { EuiPageHeaderProps, EuiPageTemplateProps, useIsWithinMaxBreakpoint } from '@elastic/eui'; import { useKibana } from '@kbn/kibana-react-plugin/public'; import { useInspectorContext } from '@kbn/observability-plugin/public'; import { ClientPluginsStart } from '../../../../../plugin'; import { EmptyStateLoading } from '../../monitors_page/overview/empty_state/empty_state_loading'; import { EmptyStateError } from '../../monitors_page/overview/empty_state/empty_state_error'; import { useHasData } from '../../monitors_page/overview/empty_state/use_has_data'; -import { useBreakpoints } from '../../../hooks'; interface Props { path: string; @@ -36,8 +35,7 @@ export const SyntheticsPageTemplateComponent: React.FC(); - const { down } = useBreakpoints(); - const isMobile = down('s'); + const isMobile = useIsWithinMaxBreakpoint('s'); const PageTemplateComponent = observability.navigation.PageTemplate; const StyledPageTemplateComponent = useMemo(() => { diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/management/monitor_list_table/monitor_list.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/management/monitor_list_table/monitor_list.tsx index bf19c52b4c3404..968d13df594dd8 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/management/monitor_list_table/monitor_list.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/management/monitor_list_table/monitor_list.tsx @@ -13,6 +13,7 @@ import { EuiPanel, EuiSpacer, useEuiTheme, + useIsWithinMinBreakpoint, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { ListFilters } from '../list_filters/list_filters'; @@ -25,7 +26,6 @@ import { EncryptedSyntheticsSavedMonitor, } from '../../../../../../../common/runtime_types'; import { SyntheticsSettingsContext } from '../../../../contexts/synthetics_settings_context'; -import { useBreakpoints } from '../../../../hooks'; import { getMonitorListColumns } from './columns'; import * as labels from './labels'; @@ -51,7 +51,7 @@ export const MonitorList = ({ errorSummaries, }: Props) => { const { basePath } = useContext(SyntheticsSettingsContext); - const isXl = useBreakpoints().up('xl'); + const isXl = useIsWithinMinBreakpoint('xxl'); const canEditSynthetics = useCanEditSynthetics(); const { euiTheme } = useEuiTheme(); diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/hooks/index.ts b/x-pack/plugins/synthetics/public/apps/synthetics/hooks/index.ts index 35b9f786d4700d..0aabe7b54714a4 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/hooks/index.ts +++ b/x-pack/plugins/synthetics/public/apps/synthetics/hooks/index.ts @@ -7,7 +7,6 @@ export * from './use_url_params'; export * from './use_breadcrumbs'; -export * from '../../../hooks/use_breakpoints'; export * from './use_service_allowed'; export * from './use_enablement'; export * from './use_locations'; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/synthetics_app.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/synthetics_app.tsx index da86d7d9510b68..923a0b9bb16f5d 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/synthetics_app.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/synthetics_app.tsx @@ -71,7 +71,15 @@ const Application = (props: SyntheticsAppProps) => { return ( - + { - describe('useBreakpoints', () => { - const width = global.innerWidth; - - beforeEach(() => { - jest.useFakeTimers(); - }); - - afterEach(() => { - jest.runOnlyPendingTimers(); - jest.useRealTimers(); - }); - - afterAll(() => { - (global as { innerWidth: number }).innerWidth = width; - }); - - it('should only return up => false and down => true for "xs" when width is less than BREAKPOINTS.xs', () => { - (global as { innerWidth: number }).innerWidth = BREAKPOINTS.xs - 1; - const { result } = renderHook(() => useBreakpoints()); - - expect(result.current.up('xs')).toBeFalsy(); - expect(result.current.down('xs')).toBeTruthy(); - }); - - it('should only return up => true and down => false for "xs" when width is above or equal BREAKPOINTS.xs', () => { - (global as { innerWidth: number }).innerWidth = BREAKPOINTS.xs; - const { result } = renderHook(() => useBreakpoints()); - - expect(result.current.up('xs')).toBeTruthy(); - expect(result.current.down('xs')).toBeFalsy(); - }); - - it('should return down => true for "m" when width equals BREAKPOINTS.l', () => { - (global as { innerWidth: number }).innerWidth = BREAKPOINTS.l; - const { result } = renderHook(() => useBreakpoints()); - - expect(result.current.up('m')).toBeTruthy(); - expect(result.current.down('m')).toBeFalsy(); - }); - - it('should return `between` => true for "m" and "xl" when width equals BREAKPOINTS.l', () => { - (global as { innerWidth: number }).innerWidth = BREAKPOINTS.l; - const { result } = renderHook(() => useBreakpoints()); - - expect(result.current.between('m', 'xl')).toBeTruthy(); - }); - - it('should return `between` => true for "s" and "m" when width equals BREAKPOINTS.s', () => { - (global as { innerWidth: number }).innerWidth = BREAKPOINTS.s; - const { result } = renderHook(() => useBreakpoints()); - - expect(result.current.between('s', 'm')).toBeTruthy(); - }); - - it('should return up => true for all when size is > xxxl+', () => { - (global as { innerWidth: number }).innerWidth = 3000; - const { result } = renderHook(() => useBreakpoints()); - - expect(result.current.up('xs')).toBeTruthy(); - expect(result.current.up('s')).toBeTruthy(); - expect(result.current.up('m')).toBeTruthy(); - expect(result.current.up('l')).toBeTruthy(); - expect(result.current.up('xl')).toBeTruthy(); - expect(result.current.up('xxl')).toBeTruthy(); - expect(result.current.up('xxxl')).toBeTruthy(); - }); - - it('should determine `isIpad (Portrait)', () => { - (global as { innerWidth: number }).innerWidth = 768; - const { result } = renderHook(() => useBreakpoints()); - - const isIpad = result.current.up('m') && result.current.down('l'); - expect(isIpad).toEqual(true); - }); - - it('should determine `isMobile (Portrait)`', () => { - (global as { innerWidth: number }).innerWidth = 480; - const { result } = renderHook(() => useBreakpoints()); - - const isMobile = result.current.up('xs') && result.current.down('s'); - expect(isMobile).toEqual(true); - }); - }); -}); diff --git a/x-pack/plugins/synthetics/public/hooks/use_breakpoints.ts b/x-pack/plugins/synthetics/public/hooks/use_breakpoints.ts deleted file mode 100644 index 9398a5fcd15fe7..00000000000000 --- a/x-pack/plugins/synthetics/public/hooks/use_breakpoints.ts +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { useCallback, useState } from 'react'; -import useWindowSize from 'react-use/lib/useWindowSize'; -import useDebounce from 'react-use/lib/useDebounce'; - -import { BREAKPOINTS, EuiBreakpointSize } from '@elastic/eui'; - -// Custom breakpoints -const BREAKPOINT_XL = 1599; // Overriding the theme's default 'xl' breakpoint -const BREAKPOINT_XXL = 1599; -const BREAKPOINT_XXXL = 2000; - -export type BreakpointKey = EuiBreakpointSize | 'xxl' | 'xxxl'; - -type BreakpointPredicate = (breakpointKey: BreakpointKey) => boolean; -type BreakpointRangePredicate = (from: BreakpointKey, to: BreakpointKey) => boolean; - -/** - * Returns the predicates functions used to determine whether the current device's width is above or below the asked - * breakpoint. (Implementation inspired by React Material UI). - * - * @example - * const { breakpoints } = useBreakpoints(); - * const isMobile = breakpoint.down('m'); - * - * @example - * const { breakpoints } = useBreakpoints(); - * const isTablet = breakpoint.between('m', 'l'); - * - * @param debounce {number} Debounce interval for optimization - * - * @returns { {up: BreakpointPredicate, down: BreakpointPredicate, between: BreakpointRangePredicate} } - * Returns object containing predicates which determine whether the current device's width lies above, below or - * in-between the given breakpoint(s) - * { - * up => Returns `true` if the current width is equal or above (inclusive) the given breakpoint size, - * or `false` otherwise. - * down => Returns `true` if the current width is below (exclusive) the given breakpoint size, or `false` otherwise. - * between => Returns `true` if the current width is equal or above (inclusive) the corresponding size of - * `fromBreakpointKey` AND is below (exclusive) the corresponding width of `toBreakpointKey`. - * Returns `false` otherwise. - * } - */ -export function useBreakpoints(debounce = 50) { - const { width } = useWindowSize(); - const [debouncedWidth, setDebouncedWidth] = useState(width); - - const up = useCallback( - (breakpointKey: BreakpointKey) => isUp(debouncedWidth, breakpointKey), - [debouncedWidth] - ); - const down = useCallback( - (breakpointKey: BreakpointKey) => isDown(debouncedWidth, breakpointKey), - [debouncedWidth] - ); - - const between = useCallback( - (fromBreakpointKey: BreakpointKey, toBreakpointKey: BreakpointKey) => - isBetween(debouncedWidth, fromBreakpointKey, toBreakpointKey), - [debouncedWidth] - ); - - useDebounce( - () => { - setDebouncedWidth(width); - }, - debounce, - [width] - ); - - return { up, down, between, debouncedWidth }; -} - -/** - * Returns the corresponding device width against the provided breakpoint key, either the overridden value or the - * default value from theme. - * @param key {BreakpointKey} string key representing the device breakpoint e.g. 'xs', 's', 'xxxl' - */ -function getSizeForBreakpointKey(key: BreakpointKey): number { - switch (key) { - case 'xxxl': - return BREAKPOINT_XXXL; - case 'xxl': - return BREAKPOINT_XXL; - case 'xl': - return BREAKPOINT_XL; - case 'l': - return BREAKPOINTS.l; - case 'm': - return BREAKPOINTS.m; - case 's': - return BREAKPOINTS.s; - } - - return BREAKPOINTS.xs; -} - -function isUp(size: number, breakpointKey: BreakpointKey) { - return size >= getSizeForBreakpointKey(breakpointKey); -} - -function isDown(size: number, breakpointKey: BreakpointKey) { - return size < getSizeForBreakpointKey(breakpointKey); -} - -function isBetween(size: number, fromBreakpointKey: BreakpointKey, toBreakpointKey: BreakpointKey) { - return isUp(size, fromBreakpointKey) && isDown(size, toBreakpointKey); -} diff --git a/x-pack/plugins/synthetics/public/legacy_uptime/app/uptime_app.tsx b/x-pack/plugins/synthetics/public/legacy_uptime/app/uptime_app.tsx index 748918026e057f..dc8c5918ec31ac 100644 --- a/x-pack/plugins/synthetics/public/legacy_uptime/app/uptime_app.tsx +++ b/x-pack/plugins/synthetics/public/legacy_uptime/app/uptime_app.tsx @@ -104,7 +104,15 @@ const Application = (props: UptimeAppProps) => { return ( - + { - const down = jest.fn().mockReturnValue(false); - return { - useBreakpoints: () => ({ down }), - }; -}); describe('UptimePageTemplateComponent', () => { describe('styling', () => { @@ -34,7 +26,7 @@ describe('UptimePageTemplateComponent', () => { }); it('applies the header centering on mobile', () => { - (useBreakpoints().down as jest.Mock).mockReturnValue(true); + window.innerWidth = 600; const { container } = render(); expect(container.firstChild).toMatchSnapshot(); }); diff --git a/x-pack/plugins/synthetics/public/legacy_uptime/app/uptime_page_template.tsx b/x-pack/plugins/synthetics/public/legacy_uptime/app/uptime_page_template.tsx index 9822ec130a8bfb..df7735aef2695a 100644 --- a/x-pack/plugins/synthetics/public/legacy_uptime/app/uptime_page_template.tsx +++ b/x-pack/plugins/synthetics/public/legacy_uptime/app/uptime_page_template.tsx @@ -7,7 +7,7 @@ import React, { useEffect, useMemo } from 'react'; import styled from 'styled-components'; -import { EuiPageHeaderProps, EuiPageTemplateProps } from '@elastic/eui'; +import { EuiPageHeaderProps, EuiPageTemplateProps, useIsWithinMaxBreakpoint } from '@elastic/eui'; import { useKibana } from '@kbn/kibana-react-plugin/public'; import { useInspectorContext } from '@kbn/observability-plugin/public'; import { CERTIFICATES_ROUTE, OVERVIEW_ROUTE } from '../../../common/constants'; @@ -16,7 +16,6 @@ import { useNoDataConfig } from './use_no_data_config'; import { EmptyStateLoading } from '../components/overview/empty_state/empty_state_loading'; import { EmptyStateError } from '../components/overview/empty_state/empty_state_error'; import { useHasData } from '../components/overview/empty_state/use_has_data'; -import { useBreakpoints } from '../../hooks/use_breakpoints'; interface Props { path: string; @@ -38,8 +37,7 @@ export const UptimePageTemplateComponent: React.FC const { services: { observability }, } = useKibana(); - const { down } = useBreakpoints(); - const isMobile = down('s'); + const isMobile = useIsWithinMaxBreakpoint('s'); const PageTemplateComponent = observability.navigation.PageTemplate; const StyledPageTemplateComponent = useMemo(() => { diff --git a/x-pack/plugins/synthetics/public/legacy_uptime/components/monitor/ping_list/columns/ping_timestamp/step_image_caption.tsx b/x-pack/plugins/synthetics/public/legacy_uptime/components/monitor/ping_list/columns/ping_timestamp/step_image_caption.tsx index 73996c4e3a1b79..b37daa81e2349d 100644 --- a/x-pack/plugins/synthetics/public/legacy_uptime/components/monitor/ping_list/columns/ping_timestamp/step_image_caption.tsx +++ b/x-pack/plugins/synthetics/public/legacy_uptime/components/monitor/ping_list/columns/ping_timestamp/step_image_caption.tsx @@ -6,11 +6,17 @@ */ import React, { MouseEvent, useEffect } from 'react'; -import { EuiButtonEmpty, EuiFlexGroup, EuiFlexItem, EuiText, useEuiTheme } from '@elastic/eui'; +import { + EuiButtonEmpty, + EuiFlexGroup, + EuiFlexItem, + EuiText, + useEuiTheme, + useIsWithinMaxBreakpoint, +} from '@elastic/eui'; import { euiStyled } from '@kbn/kibana-react-plugin/common'; import { ScreenshotRefImageData } from '../../../../../../../common/runtime_types'; -import { useBreakpoints } from '../../../../../../hooks/use_breakpoints'; import { nextAriaLabel, prevAriaLabel } from './translations'; @@ -38,7 +44,7 @@ export const StepImageCaption: React.FC = ({ onVisible, }) => { const { euiTheme } = useEuiTheme(); - const breakpoints = useBreakpoints(); + const isSmall = useIsWithinMaxBreakpoint('m'); useEffect(() => { onVisible(true); @@ -48,8 +54,6 @@ export const StepImageCaption: React.FC = ({ // eslint-disable-next-line react-hooks/exhaustive-deps }, []); - const isSmall = breakpoints.down('m'); - return ( { diff --git a/x-pack/plugins/synthetics/public/legacy_uptime/components/monitor_management/monitor_list/monitor_list.tsx b/x-pack/plugins/synthetics/public/legacy_uptime/components/monitor_management/monitor_list/monitor_list.tsx index 074eaea4177d08..c603035130ca33 100644 --- a/x-pack/plugins/synthetics/public/legacy_uptime/components/monitor_management/monitor_list/monitor_list.tsx +++ b/x-pack/plugins/synthetics/public/legacy_uptime/components/monitor_management/monitor_list/monitor_list.tsx @@ -12,6 +12,7 @@ import { EuiPanel, EuiSpacer, EuiText, + useIsWithinMinBreakpoint, } from '@elastic/eui'; import { EuiTableSortingType } from '@elastic/eui/src/components/basic_table/table_types'; import { i18n } from '@kbn/i18n'; @@ -30,7 +31,6 @@ import { BrowserFields, } from '../../../../../common/runtime_types'; import { UptimeSettingsContext } from '../../../contexts'; -import { useBreakpoints } from '../../../../hooks/use_breakpoints'; import { MonitorManagementList as MonitorManagementListState } from '../../../state/reducers/monitor_management'; import * as labels from '../../overview/monitor_list/translations'; import { Actions } from './actions'; @@ -70,7 +70,7 @@ export const MonitorManagementList = ({ errorSummaries, }: Props) => { const { basePath } = useContext(UptimeSettingsContext); - const isXl = useBreakpoints().up('xl'); + const isXl = useIsWithinMinBreakpoint('xxl'); const { total } = list as MonitorManagementListState['list']; const monitors: EncryptedSyntheticsMonitorWithId[] = useMemo( diff --git a/x-pack/plugins/synthetics/public/legacy_uptime/components/overview/monitor_list/monitor_list.tsx b/x-pack/plugins/synthetics/public/legacy_uptime/components/overview/monitor_list/monitor_list.tsx index a57bbf9d71bd8b..4ca114264feca2 100644 --- a/x-pack/plugins/synthetics/public/legacy_uptime/components/overview/monitor_list/monitor_list.tsx +++ b/x-pack/plugins/synthetics/public/legacy_uptime/components/overview/monitor_list/monitor_list.tsx @@ -5,7 +5,6 @@ * 2.0. */ import React, { useState } from 'react'; -import useWindowSize from 'react-use/lib/useWindowSize'; import useDebounce from 'react-use/lib/useDebounce'; import { EuiButtonIcon, @@ -15,7 +14,7 @@ import { EuiLink, EuiPanel, EuiSpacer, - getBreakpoint, + useCurrentEuiBreakpoint, } from '@elastic/eui'; import { euiStyled } from '@kbn/kibana-react-plugin/common'; import { X509Expiry } from '../../../../../common/runtime_types'; @@ -61,15 +60,17 @@ export const MonitorListComponent: ({ setPageSize, }) => { const [expandedDrawerIds, updateExpandedDrawerIds] = useState([]); - const { width } = useWindowSize(); + const currentBreakpoint = useCurrentEuiBreakpoint(); const [hideExtraColumns, setHideExtraColumns] = useState(false); useDebounce( () => { - setHideExtraColumns(['m', 'l'].includes(getBreakpoint(width) ?? '')); + if (currentBreakpoint) { + setHideExtraColumns(['m', 'l'].includes(currentBreakpoint)); + } }, 50, - [width] + [currentBreakpoint] ); const items = list.summaries ?? []; diff --git a/x-pack/plugins/synthetics/public/legacy_uptime/pages/synthetics/checks_navigation.tsx b/x-pack/plugins/synthetics/public/legacy_uptime/pages/synthetics/checks_navigation.tsx index f9d98b7b640c68..f9573da57d9149 100644 --- a/x-pack/plugins/synthetics/public/legacy_uptime/pages/synthetics/checks_navigation.tsx +++ b/x-pack/plugins/synthetics/public/legacy_uptime/pages/synthetics/checks_navigation.tsx @@ -6,13 +6,18 @@ */ import React from 'react'; -import { EuiButtonEmpty, EuiFlexGroup, EuiFlexItem, EuiText } from '@elastic/eui'; +import { + EuiButtonEmpty, + EuiFlexGroup, + EuiFlexItem, + EuiText, + useIsWithinMaxBreakpoint, +} from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n-react'; import { useHistory } from 'react-router-dom'; import moment from 'moment'; import { SyntheticsJourneyApiResponse } from '../../../../common/runtime_types/ping'; import { getShortTimeStamp } from '../../components/overview/monitor_list/columns/monitor_status_column'; -import { useBreakpoints } from '../../../hooks/use_breakpoints'; interface Props { timestamp: string; @@ -21,9 +26,7 @@ interface Props { export const ChecksNavigation = ({ timestamp, details }: Props) => { const history = useHistory(); - const { down } = useBreakpoints(); - - const isMobile = down('s'); + const isMobile = useIsWithinMaxBreakpoint('s'); return ( diff --git a/x-pack/plugins/ux/public/application/ux_app.tsx b/x-pack/plugins/ux/public/application/ux_app.tsx index 2e26703cc27819..e96012cd41d126 100644 --- a/x-pack/plugins/ux/public/application/ux_app.tsx +++ b/x-pack/plugins/ux/public/application/ux_app.tsx @@ -142,7 +142,15 @@ export function UXAppRoot({ lens, }} > - + diff --git a/x-pack/plugins/ux/public/hooks/use_breakpoints.ts b/x-pack/plugins/ux/public/hooks/use_breakpoints.ts index f87ddb929b66a2..9ec8b20bb472d7 100644 --- a/x-pack/plugins/ux/public/hooks/use_breakpoints.ts +++ b/x-pack/plugins/ux/public/hooks/use_breakpoints.ts @@ -5,42 +5,23 @@ * 2.0. */ -import { useState } from 'react'; -import useWindowSize from 'react-use/lib/useWindowSize'; -import useDebounce from 'react-use/lib/useDebounce'; import { - getBreakpoint, - isWithinMaxBreakpoint, - isWithinMinBreakpoint, + useIsWithinMaxBreakpoint, + useIsWithinMinBreakpoint, } from '@elastic/eui'; -export type Breakpoints = ReturnType; - -export function getScreenSizes(windowWidth: number) { - return { - isXSmall: isWithinMaxBreakpoint(windowWidth, 'xs'), - isSmall: isWithinMaxBreakpoint(windowWidth, 's'), - isMedium: isWithinMaxBreakpoint(windowWidth, 'm'), - isLarge: isWithinMaxBreakpoint(windowWidth, 'l'), - isXl: isWithinMaxBreakpoint(windowWidth, 1599), - isXXL: isWithinMaxBreakpoint(windowWidth, 1999), - isXXXL: isWithinMinBreakpoint(windowWidth, 2000), - }; -} +export type Breakpoints = Record; export function useBreakpoints() { - const { width } = useWindowSize(); - const [breakpoint, setBreakpoint] = useState(getBreakpoint(width)); - const [screenSizes, setScreenSizes] = useState(getScreenSizes(width)); - - useDebounce( - () => { - setBreakpoint(getBreakpoint(width)); - setScreenSizes(getScreenSizes(width)); - }, - 50, - [width] - ); + const screenSizes = { + isXSmall: useIsWithinMaxBreakpoint('xs'), + isSmall: useIsWithinMaxBreakpoint('s'), + isMedium: useIsWithinMaxBreakpoint('m'), + isLarge: useIsWithinMaxBreakpoint('l'), + isXl: useIsWithinMaxBreakpoint('xl'), + isXXL: useIsWithinMaxBreakpoint('xxl'), + isXXXL: useIsWithinMinBreakpoint('xxxl'), + }; - return { ...screenSizes, breakpoint, width }; + return screenSizes; } diff --git a/yarn.lock b/yarn.lock index 2b17ad8d660db7..cc735318248146 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1530,10 +1530,10 @@ resolved "https://registry.yarnpkg.com/@elastic/eslint-plugin-eui/-/eslint-plugin-eui-0.0.2.tgz#56b9ef03984a05cc213772ae3713ea8ef47b0314" integrity sha512-IoxURM5zraoQ7C8f+mJb9HYSENiZGgRVcG4tLQxE61yHNNRDXtGDWTZh8N1KIHcsqN1CEPETjuzBXkJYF/fDiQ== -"@elastic/eui@63.0.6": - version "63.0.6" - resolved "https://registry.yarnpkg.com/@elastic/eui/-/eui-63.0.6.tgz#8f2d1d0bd1fd39ca67e9c65ecfef2dc7222af100" - integrity sha512-3uW/Q1VA9CMRLzm8lGhTHcBnyLhyoLPnJ3GdXxgTC4zzDlIlIsxrSnn+7sDxAsyVgnSCvHlO0dVbrEf1+G7Y8w== +"@elastic/eui@64.0.4": + version "64.0.4" + resolved "https://registry.yarnpkg.com/@elastic/eui/-/eui-64.0.4.tgz#4a6a997a3f43f459c82e3b992ac2e6ab318d5a12" + integrity sha512-4wpZcVJyNvxfZA58kVSwnJxIbWCrFriU6vARr/DoDB6Vvt/5zHeFrHzXFjdo+hqTWZApPoEQlK7aJ7FDZTEbkw== dependencies: "@types/chroma-js" "^2.0.0" "@types/lodash" "^4.14.160"