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

[CSS-in-JS] Convert EuiBreakpoint Mixin to Emotion #6057

Merged
merged 15 commits into from
Jul 20, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions src-docs/src/views/theme/breakpoints/_breakpoints_js.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,11 @@ import {
EuiBreakpointSize,
EuiCode,
EuiThemeBreakpoints,
useEuiBreakpoint,
} from '../../../../../src';

import { css } from '@emotion/react';

import { EuiThemeBreakpoints as _EuiThemeBreakpoints } from '../_props';
import { getPropsFromComponent } from '../../../services/props/get_props';
import { ThemeExample } from '../_components/_theme_example';
Expand Down Expand Up @@ -132,6 +135,51 @@ export default () => {
snippet="useIsWithinBreakpoints(['l', 'xl'])"
snippetLanguage="js"
/>

<ThemeExample
title={<code>useEuiBreakpoint(sizes[])</code>}
type="hook"
description={
<>
<p>
Given an array of breakpoint keys, this hook generates a CSS media
query string based on the minimum width and maximum width
provided.
</p>
<p>
You can also create media queries with a{' '}
<EuiCode>(min-width)</EuiCode> only or{' '}
<EuiCode>(max-width)</EuiCode> only by utilizing the{' '}
<EuiCode>0</EuiCode> and <EuiCode>Infinity</EuiCode> arguments.
</p>
</>
}
example={
<p
css={css`
${useEuiBreakpoint([0, 'm'])} {
color: ${euiTheme.colors.dangerText};
}
${useEuiBreakpoint(['m', 'xl'])} {
color: ${euiTheme.colors.warningText};
}
${useEuiBreakpoint(['xl', Infinity])} {
color: ${euiTheme.colors.successText};
}
`}
>
This text is red on screens narrower than `m`, yellow between `m` to
`xl` breakpoints, and green on screens wider than `xl`.
</p>
}
snippet={`\${useEuiBreakpoint(['m', 'xl'])} {
color: red;
}
\${useEuiBreakpoint(['xl', Infinity])} {
color: green;
}`}
snippetLanguage="emotion"
/>
</>
);
};
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`useEuiBreakpoint 0 as a first argument should not render a min-width query (0 and l) 1`] = `"@media only screen and (max-width: 991px)"`;

exports[`useEuiBreakpoint 0 as a first argument should not render a min-width query (0 and m) 1`] = `"@media only screen and (max-width: 767px)"`;

exports[`useEuiBreakpoint 0 as a first argument should not render a min-width query (0 and s) 1`] = `"@media only screen and (max-width: 574px)"`;

exports[`useEuiBreakpoint 0 as a first argument should not render a min-width query (0 and xl) 1`] = `"@media only screen and (max-width: 1199px)"`;

exports[`useEuiBreakpoint 0 as a first argument should not render a min-width query (0 and xs) 1`] = `"@media only screen"`;

exports[`useEuiBreakpoint Infinity as a last argument should not render a max-width query (l and Infinity) 1`] = `"@media only screen and (min-width: 992px)"`;

exports[`useEuiBreakpoint Infinity as a last argument should not render a max-width query (m and Infinity) 1`] = `"@media only screen and (min-width: 768px)"`;

exports[`useEuiBreakpoint Infinity as a last argument should not render a max-width query (s and Infinity) 1`] = `"@media only screen and (min-width: 575px)"`;

exports[`useEuiBreakpoint Infinity as a last argument should not render a max-width query (xl and Infinity) 1`] = `"@media only screen and (min-width: 1200px)"`;

exports[`useEuiBreakpoint Infinity as a last argument should not render a max-width query (xs and Infinity) 1`] = `"@media only screen"`;

exports[`useEuiBreakpoint breakpoint size arrays with more than 2 sizes should use the first and last items in the array 1`] = `"@media only screen and (min-width: 575px) and (max-width: 991px)"`;

exports[`useEuiBreakpoint common breakpoint size arrays useEuiBreakpoint returns a media query for two element breakpoint combinations (l and xl) 1`] = `"@media only screen and (min-width: 992px) and (max-width: 1199px)"`;

exports[`useEuiBreakpoint common breakpoint size arrays useEuiBreakpoint returns a media query for two element breakpoint combinations (m and l) 1`] = `"@media only screen and (min-width: 768px) and (max-width: 991px)"`;

exports[`useEuiBreakpoint common breakpoint size arrays useEuiBreakpoint returns a media query for two element breakpoint combinations (m and xl) 1`] = `"@media only screen and (min-width: 768px) and (max-width: 1199px)"`;

exports[`useEuiBreakpoint common breakpoint size arrays useEuiBreakpoint returns a media query for two element breakpoint combinations (s and l) 1`] = `"@media only screen and (min-width: 575px) and (max-width: 991px)"`;

exports[`useEuiBreakpoint common breakpoint size arrays useEuiBreakpoint returns a media query for two element breakpoint combinations (s and m) 1`] = `"@media only screen and (min-width: 575px) and (max-width: 767px)"`;

exports[`useEuiBreakpoint common breakpoint size arrays useEuiBreakpoint returns a media query for two element breakpoint combinations (s and xl) 1`] = `"@media only screen and (min-width: 575px) and (max-width: 1199px)"`;

exports[`useEuiBreakpoint common breakpoint size arrays useEuiBreakpoint returns a media query for two element breakpoint combinations (xs and l) 1`] = `"@media only screen and (max-width: 991px)"`;

exports[`useEuiBreakpoint common breakpoint size arrays useEuiBreakpoint returns a media query for two element breakpoint combinations (xs and m) 1`] = `"@media only screen and (max-width: 767px)"`;

exports[`useEuiBreakpoint common breakpoint size arrays useEuiBreakpoint returns a media query for two element breakpoint combinations (xs and s) 1`] = `"@media only screen and (max-width: 574px)"`;

exports[`useEuiBreakpoint common breakpoint size arrays useEuiBreakpoint returns a media query for two element breakpoint combinations (xs and xl) 1`] = `"@media only screen and (max-width: 1199px)"`;

exports[`useEuiBreakpoint single breakpoint sizes should infer the next breakpoint size as max-width l 1`] = `"@media only screen and (min-width: 992px) and (max-width: 1199px)"`;

exports[`useEuiBreakpoint single breakpoint sizes should infer the next breakpoint size as max-width m 1`] = `"@media only screen and (min-width: 768px) and (max-width: 991px)"`;

exports[`useEuiBreakpoint single breakpoint sizes should infer the next breakpoint size as max-width s 1`] = `"@media only screen and (min-width: 575px) and (max-width: 767px)"`;

exports[`useEuiBreakpoint single breakpoint sizes should infer the next breakpoint size as max-width xl 1`] = `"@media only screen and (min-width: 1200px)"`;

exports[`useEuiBreakpoint single breakpoint sizes should infer the next breakpoint size as max-width xs 1`] = `"@media only screen and (max-width: 574px)"`;
192 changes: 192 additions & 0 deletions src/global_styling/mixins/_responsive.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
/*
* 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 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/

import { testCustomHook } from '../../test/internal';
import { EuiThemeBreakpoints, _EuiThemeBreakpoint } from '../variables';
import { useEuiBreakpoint } from './_responsive';

describe('useEuiBreakpoint', () => {
describe('common breakpoint size arrays', () => {
const possibleTwoElementBreakpointCombinations = [];
for (let i = 0; i < EuiThemeBreakpoints.length; i++) {
for (let j = 1; j < EuiThemeBreakpoints.length; j++) {
if (j > i) {
possibleTwoElementBreakpointCombinations.push([
`${EuiThemeBreakpoints[i]}`,
`${EuiThemeBreakpoints[j]}`,
]);
}
}
}

test.each(possibleTwoElementBreakpointCombinations)(
'useEuiBreakpoint returns a media query for two element breakpoint combinations (%s and %s)',
(minSize, maxSize) => {
expect(
testCustomHook(() =>
useEuiBreakpoint([
minSize as _EuiThemeBreakpoint,
maxSize as _EuiThemeBreakpoint,
])
).return
).toMatchSnapshot();
}
);
});

describe('0 as a first argument should not render a min-width query', () => {
EuiThemeBreakpoints.forEach((size) => {
test(`(0 and ${size})`, () => {
expect(
testCustomHook(() => useEuiBreakpoint([0, size])).return
).toMatchSnapshot();
});
});
});

describe('Infinity as a last argument should not render a max-width query', () => {
EuiThemeBreakpoints.forEach((size) => {
test(`(${size} and Infinity)`, () => {
expect(
testCustomHook(() => useEuiBreakpoint([size, Infinity])).return
).toMatchSnapshot();
});
});
});

describe('breakpoint size arrays with more than 2 sizes', () => {
it('should use the first and last items in the array', () => {
expect(
testCustomHook(() => useEuiBreakpoint(['s', 'm', 'l'])).return
).toMatchSnapshot();
});
});

describe('single breakpoint sizes should infer the next breakpoint size as max-width', () => {
EuiThemeBreakpoints.forEach((size) => {
test(`${size}`, () => {
expect(
testCustomHook(() => useEuiBreakpoint([size])).return
).toMatchSnapshot();
});
});
});

describe('invalid arguments', () => {
const fallbackOutput = '@media only screen';

const oldConsoleError = console.warn;
let consoleStub: jest.Mock;
beforeEach(() => {
console.warn = consoleStub = jest.fn();
});
afterEach(() => {
console.warn = oldConsoleError;
});

describe('invalid array sizes', () => {
afterEach(() => {
expect(consoleStub).toHaveBeenCalledTimes(1);
expect(consoleStub).toHaveBeenLastCalledWith(
'Pass more than one breakpoint size'
);
});

it('empty array', () => {
expect(testCustomHook(() => useEuiBreakpoint([])).return).toEqual(
fallbackOutput
);
});

it('invalid single non-breakpoint size', () => {
expect(testCustomHook(() => useEuiBreakpoint([0])).return).toEqual(
fallbackOutput
);
});

it('invalid single non-breakpoint size', () => {
expect(
testCustomHook(() => useEuiBreakpoint([Infinity])).return
).toEqual(fallbackOutput);
});
});

describe('invalid breakpoint keys', () => {
afterEach(() => {
expect(consoleStub).toHaveBeenCalledTimes(2);
expect(consoleStub).toHaveBeenCalledWith(
'Invalid min-width breakpoint size passed'
);
expect(consoleStub).toHaveBeenCalledWith(
'Invalid max-width breakpoint size passed'
);
});

it('warns when invalid size key strings are passed', () => {
expect(
// @ts-expect-error deliberate incorrect type
testCustomHook(() => useEuiBreakpoint(['teeny-tiny', 'SUPERMASSIVE']))
.return
).toEqual(fallbackOutput);
});

it('warns when invalid size numbers are passed', () => {
expect(
testCustomHook(() => useEuiBreakpoint([100, 400])).return // we might support this someday, but today is not that day
).toEqual(fallbackOutput);
});

it('warns when 0 and Infinity are used in the wrong position', () => {
expect(
testCustomHook(() => useEuiBreakpoint([Infinity, 0])).return
).toEqual(fallbackOutput);
});
});

describe('invalid breakpoint size order', () => {
afterEach(() => {
expect(consoleStub).toHaveBeenCalledTimes(1);
expect(consoleStub).toHaveBeenLastCalledWith(
'Invalid breakpoint sizes passed. The first size should be smaller than the last size'
);
});

it('warns if min breakpoint is not smaller than the max breakpoint', () => {
expect(
testCustomHook(() => useEuiBreakpoint(['xl', 'xs'])).return
).toEqual(fallbackOutput);
});

it('warns if the min/max breakpoints are equal', () => {
expect(
testCustomHook(() => useEuiBreakpoint(['s', 's'])).return
).toEqual(fallbackOutput);
});
});

describe('valid but funky breakpoint combos', () => {
afterEach(() => {
expect(consoleStub).not.toHaveBeenCalled();
});

test('0 and xs', () => {
// Since xs is (currently) already 0, this should output nothing
expect(
testCustomHook(() => useEuiBreakpoint([0, 'xs'])).return
).toEqual(fallbackOutput);
});

test('xs and infinity', () => {
// Since xs is (currently) 0, there should be no min or max width
expect(
testCustomHook(() => useEuiBreakpoint(['xs', Infinity])).return
).toEqual(fallbackOutput);
});
});
});
});
Loading