Skip to content

Commit

Permalink
Changing popoverButtonMaxBreakpoint to an array of `popoverButtonBr…
Browse files Browse the repository at this point in the history
…eakpoints`
  • Loading branch information
cchaos committed Sep 10, 2020
1 parent 64440cc commit b697cba
Show file tree
Hide file tree
Showing 9 changed files with 102 additions and 41 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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**
Expand Down
2 changes: 1 addition & 1 deletion src-docs/src/views/header/header_elastic_pattern.js
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,7 @@ export default ({ theme }) => {
<EuiIcon type="search" size="m" />
</EuiHeaderSectionItemButton>
}
popoverButtonMaxBreakpoint="s"
popoverButtonBreakpoints={['xs', 's']}
emptyMessage={
<EuiSelectableMessage style={{ minHeight: 300 }}>
<p>
Expand Down
2 changes: 1 addition & 1 deletion src-docs/src/views/selectable/search.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ export default () => {
className: 'customPopoverClass',
}}
popoverButton={<EuiButton>Mobile toggle</EuiButton>}
popoverButtonMaxBreakpoint="s"
popoverButtonBreakpoints={['xs', 's']}
popoverFooter={
<EuiText color="subdued" size="xs">
<EuiFlexGroup
Expand Down
6 changes: 3 additions & 3 deletions src-docs/src/views/selectable/selectable_example.js
Original file line number Diff line number Diff line change
Expand Up @@ -561,9 +561,9 @@ export const SelectableExample = {
<p>
This is a great way to handle reducing the size of the component for
smaller screens. The component offers a helper prop called{' '}
<EuiCode>popoverButtonMaxBreakpoint</EuiCode> which will only use
the <EuiCode>popoverButton</EuiCode> if the window width is equal to
or smaller than the named breakpoint.
<EuiCode>popoverButtonBreakpoints</EuiCode> which will only render
the <EuiCode>popoverButton</EuiCode> if the window size matches
named breakpoint(s).
</p>
</Fragment>
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ exports[`EuiSelectableTemplateSitewide is rendered 1`] = `
</div>
`;

exports[`EuiSelectableTemplateSitewide props popoverButton is not rendered with popoverButtonMaxBreakpoint xs 1`] = `
exports[`EuiSelectableTemplateSitewide props popoverButton is not rendered with popoverButtonBreakpoints xs 1`] = `
<div
class="euiSelectable euiSelectableTemplateSitewide"
>
Expand Down Expand Up @@ -111,7 +111,7 @@ exports[`EuiSelectableTemplateSitewide props popoverButton is rendered 1`] = `
</div>
`;

exports[`EuiSelectableTemplateSitewide props popoverButton is rendered with popoverButtonMaxBreakpoint m 1`] = `
exports[`EuiSelectableTemplateSitewide props popoverButton is rendered with popoverButtonBreakpoints m 1`] = `
<div
class="euiSelectable euiSelectableTemplateSitewide"
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -148,24 +148,24 @@ describe('EuiSelectableTemplateSitewide', () => {
expect(component).toMatchSnapshot();
});

test('is rendered with popoverButtonMaxBreakpoint m', () => {
test('is rendered with popoverButtonBreakpoints m', () => {
const component = render(
<EuiSelectableTemplateSitewide
options={options}
popoverButton={<button>Button</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(
<EuiSelectableTemplateSitewide
options={options}
popoverButton={<button>Button</button>}
popoverButtonMaxBreakpoint={'xs'}
popoverButtonBreakpoints={['xs']}
/>
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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<EuiSelectableTemplateSitewideProps> = ({
Expand All @@ -88,25 +88,23 @@ export const EuiSelectableTemplateSitewide: FunctionComponent<EuiSelectableTempl
listProps,
isLoading,
popoverButton,
popoverButtonMaxBreakpoint,
popoverButtonBreakpoints,
...rest
}) => {
/**
* 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);
}
Expand Down
76 changes: 60 additions & 16 deletions src/services/breakpoint.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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", () => {
Expand All @@ -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);
Expand Down Expand Up @@ -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);
Expand All @@ -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);
});
});
});
});
19 changes: 19 additions & 0 deletions src/services/breakpoint.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

0 comments on commit b697cba

Please sign in to comment.