From b697cba138b1557f38e18fc4b73e34cf43be76b7 Mon Sep 17 00:00:00 2001 From: cchaos Date: Thu, 10 Sep 2020 18:03:34 -0400 Subject: [PATCH] Changing `popoverButtonMaxBreakpoint` to an array of `popoverButtonBreakpoints` --- CHANGELOG.md | 2 +- .../views/header/header_elastic_pattern.js | 2 +- src-docs/src/views/selectable/search.tsx | 2 +- .../views/selectable/selectable_example.js | 6 +- ...selectable_template_sitewide.test.tsx.snap | 4 +- .../selectable_template_sitewide.test.tsx | 8 +- .../selectable_template_sitewide.tsx | 24 +++--- src/services/breakpoint.test.ts | 76 +++++++++++++++---- src/services/breakpoint.ts | 19 +++++ 9 files changed, 102 insertions(+), 41 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5e0e146144a6..c5c22de900b1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,7 @@ - Added `.browserslistrc` for global browser support reference ([#4022](https://github.com/elastic/eui/pull/4022)) - Added ability to specify `color` of `EuiHeaderLink` ([#4008](https://github.com/elastic/eui/pull/4008)) - Added `boolean` type to the `notification` prop of `EuiHeaderSectionItemButton` to show a simple dot ([#4008](https://github.com/elastic/eui/pull/4008)) -- Added `popoverButton` and `popoverButtonMaxBreakpoint` props to `EuiSelectableTemplateSitewide` for responsive capabilities ([#4008](https://github.com/elastic/eui/pull/4008)) +- Added `popoverButton` and `popoverButtonBreakpoints` props to `EuiSelectableTemplateSitewide` for responsive capabilities ([#4008](https://github.com/elastic/eui/pull/4008)) - Added `isWithinMaxBreakpoint` service ([#4008](https://github.com/elastic/eui/pull/4008)) **Bug fixes** diff --git a/src-docs/src/views/header/header_elastic_pattern.js b/src-docs/src/views/header/header_elastic_pattern.js index 84d767b0abb7..c365f823f3be 100644 --- a/src-docs/src/views/header/header_elastic_pattern.js +++ b/src-docs/src/views/header/header_elastic_pattern.js @@ -253,7 +253,7 @@ export default ({ theme }) => { } - popoverButtonMaxBreakpoint="s" + popoverButtonBreakpoints={['xs', 's']} emptyMessage={

diff --git a/src-docs/src/views/selectable/search.tsx b/src-docs/src/views/selectable/search.tsx index fc4fc4705bb5..dee0ea737921 100644 --- a/src-docs/src/views/selectable/search.tsx +++ b/src-docs/src/views/selectable/search.tsx @@ -97,7 +97,7 @@ export default () => { className: 'customPopoverClass', }} popoverButton={Mobile toggle} - popoverButtonMaxBreakpoint="s" + popoverButtonBreakpoints={['xs', 's']} popoverFooter={ This is a great way to handle reducing the size of the component for smaller screens. The component offers a helper prop called{' '} - popoverButtonMaxBreakpoint which will only use - the popoverButton if the window width is equal to - or smaller than the named breakpoint. + popoverButtonBreakpoints which will only render + the popoverButton if the window size matches + named breakpoint(s).

), diff --git a/src/components/selectable/selectable_templates/__snapshots__/selectable_template_sitewide.test.tsx.snap b/src/components/selectable/selectable_templates/__snapshots__/selectable_template_sitewide.test.tsx.snap index f41364d06255..c3f2b69f4850 100644 --- a/src/components/selectable/selectable_templates/__snapshots__/selectable_template_sitewide.test.tsx.snap +++ b/src/components/selectable/selectable_templates/__snapshots__/selectable_template_sitewide.test.tsx.snap @@ -47,7 +47,7 @@ exports[`EuiSelectableTemplateSitewide is rendered 1`] = ` `; -exports[`EuiSelectableTemplateSitewide props popoverButton is not rendered with popoverButtonMaxBreakpoint xs 1`] = ` +exports[`EuiSelectableTemplateSitewide props popoverButton is not rendered with popoverButtonBreakpoints xs 1`] = `
@@ -111,7 +111,7 @@ exports[`EuiSelectableTemplateSitewide props popoverButton is rendered 1`] = `
`; -exports[`EuiSelectableTemplateSitewide props popoverButton is rendered with popoverButtonMaxBreakpoint m 1`] = ` +exports[`EuiSelectableTemplateSitewide props popoverButton is rendered with popoverButtonBreakpoints m 1`] = `
diff --git a/src/components/selectable/selectable_templates/selectable_template_sitewide.test.tsx b/src/components/selectable/selectable_templates/selectable_template_sitewide.test.tsx index be476400f7fd..602ebb155640 100644 --- a/src/components/selectable/selectable_templates/selectable_template_sitewide.test.tsx +++ b/src/components/selectable/selectable_templates/selectable_template_sitewide.test.tsx @@ -148,24 +148,24 @@ describe('EuiSelectableTemplateSitewide', () => { expect(component).toMatchSnapshot(); }); - test('is rendered with popoverButtonMaxBreakpoint m', () => { + test('is rendered with popoverButtonBreakpoints m', () => { const component = render( Button} - popoverButtonMaxBreakpoint={'m'} + popoverButtonBreakpoints={['xs', 's', 'm']} /> ); expect(component).toMatchSnapshot(); }); - test('is not rendered with popoverButtonMaxBreakpoint xs', () => { + test('is not rendered with popoverButtonBreakpoints xs', () => { const component = render( Button} - popoverButtonMaxBreakpoint={'xs'} + popoverButtonBreakpoints={['xs']} /> ); diff --git a/src/components/selectable/selectable_templates/selectable_template_sitewide.tsx b/src/components/selectable/selectable_templates/selectable_template_sitewide.tsx index d93fcb7a3234..cda9f83b83a0 100644 --- a/src/components/selectable/selectable_templates/selectable_template_sitewide.tsx +++ b/src/components/selectable/selectable_templates/selectable_template_sitewide.tsx @@ -40,7 +40,7 @@ import { } from './selectable_template_sitewide_option'; import { EuiBreakpointSize, - isWithinMaxBreakpoint, + isWithinBreakpoints, } from '../../../services/breakpoint'; import { throttle } from '../../color_picker/utils'; import { EuiSpacer } from '../../spacer'; @@ -71,10 +71,10 @@ export type EuiSelectableTemplateSitewideProps = Partial< */ popoverButton?: ReactElement; /** - * Pass a max breakpoint at which to show the `popoverButton`. + * Pass an array of named breakpoints for which to show the `popoverButton`. * If `undefined`, the `popoverButton` will always show (if provided) */ - popoverButtonMaxBreakpoint?: EuiBreakpointSize; + popoverButtonBreakpoints?: EuiBreakpointSize[]; }; export const EuiSelectableTemplateSitewide: FunctionComponent = ({ @@ -88,25 +88,23 @@ export const EuiSelectableTemplateSitewide: FunctionComponent { /** * Breakpoint management */ const [canShowPopoverButton, setCanShowPopoverButton] = useState( - typeof window !== 'undefined' && - isWithinMaxBreakpoint( - window.innerWidth, - popoverButtonMaxBreakpoint || Infinity - ) + typeof window !== 'undefined' && popoverButtonBreakpoints + ? isWithinBreakpoints(window.innerWidth, popoverButtonBreakpoints) + : true ); const functionToCallOnWindowResize = throttle(() => { - const newWidthIsWithinBreakpoint = isWithinMaxBreakpoint( - window.innerWidth, - popoverButtonMaxBreakpoint || Infinity - ); + const newWidthIsWithinBreakpoint = popoverButtonBreakpoints + ? isWithinBreakpoints(window.innerWidth, popoverButtonBreakpoints) + : true; + if (newWidthIsWithinBreakpoint !== canShowPopoverButton) { setCanShowPopoverButton(newWidthIsWithinBreakpoint); } diff --git a/src/services/breakpoint.test.ts b/src/services/breakpoint.test.ts index e092bde97b28..fa6879330dfb 100644 --- a/src/services/breakpoint.test.ts +++ b/src/services/breakpoint.test.ts @@ -21,8 +21,17 @@ import { getBreakpoint, EuiBreakpoints, isWithinMaxBreakpoint, + isWithinBreakpoints, } from './breakpoint'; +const CUSTOM_BREAKPOINTS: EuiBreakpoints = { + xl: 1400, + l: 1078, + m: 812, + s: 667, + xs: 320, +}; + describe('getBreakpoint', () => { describe('with default BREAKPOINTS', () => { it("should return 'xs' for 320", () => { @@ -42,14 +51,6 @@ describe('getBreakpoint', () => { }); }); - const CUSTOM_BREAKPOINTS: EuiBreakpoints = { - xl: 1400, - l: 1078, - m: 812, - s: 667, - xs: 320, - }; - describe('with custom breakpoints', () => { it("should return 'undefined' for 240", () => { expect(getBreakpoint(240, CUSTOM_BREAKPOINTS)).toBe(undefined); @@ -91,14 +92,6 @@ describe('isWithinMaxBreakpoint', () => { }); }); - const CUSTOM_BREAKPOINTS: EuiBreakpoints = { - xl: 1400, - l: 1078, - m: 812, - s: 667, - xs: 320, - }; - describe('with custom breakpoints', () => { it("should return 'false' for 'xs' and 240", () => { expect(isWithinMaxBreakpoint(240, 'xs', CUSTOM_BREAKPOINTS)).toBe(false); @@ -125,4 +118,55 @@ describe('isWithinMaxBreakpoint', () => { expect(isWithinMaxBreakpoint(320, 480)).toBe(true); }); }); + + describe('isWithinBreakpoints', () => { + describe('with default BREAKPOINTS', () => { + it("should return 'true' for 'xs' and 320", () => { + expect(isWithinBreakpoints(320, ['xs'])).toBe(true); + }); + it("should return 'true' for 's' and 667", () => { + expect(isWithinBreakpoints(667, ['s'])).toBe(true); + }); + it("should return 'true' for 'm' and 812", () => { + expect(isWithinBreakpoints(812, ['m'])).toBe(true); + }); + it("should return 'true' for 'l' and 1078", () => { + expect(isWithinBreakpoints(1078, ['l'])).toBe(true); + }); + it("should return 'true' for 'xl' and 1400", () => { + expect(isWithinBreakpoints(1400, ['xl'])).toBe(true); + }); + }); + + describe('with custom breakpoints', () => { + it("should return 'false' for 'xs' and 240", () => { + expect(isWithinBreakpoints(240, ['xs'], CUSTOM_BREAKPOINTS)).toBe( + false + ); + }); + it("should return 'true' for 'xs' and 575", () => { + expect(isWithinBreakpoints(575, ['xs'], CUSTOM_BREAKPOINTS)).toBe(true); + }); + it("should return 'true' for 's' and 768", () => { + expect(isWithinBreakpoints(768, ['s'], CUSTOM_BREAKPOINTS)).toBe(true); + }); + it("should return 'true' for 'm' and 992", () => { + expect(isWithinBreakpoints(992, ['m'], CUSTOM_BREAKPOINTS)).toBe(true); + }); + it("should return 'true' for 'l' and 1200", () => { + expect(isWithinBreakpoints(1200, ['l'], CUSTOM_BREAKPOINTS)).toBe(true); + }); + it("should return 'true' for 'xl' and 1400", () => { + expect(isWithinBreakpoints(1400, ['xl'], CUSTOM_BREAKPOINTS)).toBe( + true + ); + }); + }); + + describe('with multiple sizes', () => { + it("should return 'true' for a 667 width and ['xs', 's']", () => { + expect(isWithinBreakpoints(667, ['xs', 's'])).toBe(true); + }); + }); + }); }); diff --git a/src/services/breakpoint.ts b/src/services/breakpoint.ts index 7791f5acd3bf..d1958ecac6bd 100644 --- a/src/services/breakpoint.ts +++ b/src/services/breakpoint.ts @@ -79,3 +79,22 @@ export function isWithinMaxBreakpoint( : false; } } + +/** + * Given the current `width` and an array of breakpoint keys, + * this function returns true or false if the `width` falls within + * any of the named breakpoints + * + * @param {number} width Can either be the full window width or any width + * @param {EuiBreakpointSize[]} sizes An array of named breakpoints + * @param {EuiBreakpoints} breakpoints An object with keys for sizing and values for minimum width + * @returns {boolean} Returns `true` if current breakpoint name is included in `sizes` + */ +export function isWithinBreakpoints( + width: number, + sizes: EuiBreakpointSize[], + breakpoints: EuiBreakpoints = BREAKPOINTS +): boolean { + const currentBreakpoint = getBreakpoint(width, breakpoints); + return currentBreakpoint ? sizes.includes(currentBreakpoint) : false; +}