diff --git a/src-docs/src/routes.js b/src-docs/src/routes.js index cae4d6180bd..2b4839ba7f7 100644 --- a/src-docs/src/routes.js +++ b/src-docs/src/routes.js @@ -174,6 +174,9 @@ import { PortalExample } import { ProgressExample } from './views/progress/progress_example'; + import { ResponsiveExample } + from './views/responsive/responsive_example'; + import { SearchBarExample } from './views/search_bar/search_bar_example'; @@ -341,6 +344,7 @@ const navigation = [{ name: 'Utilities', items: [ AccessibilityExample, + ResponsiveExample, DelayHideExample, ErrorBoundaryExample, HighlightExample, diff --git a/src-docs/src/views/responsive/responsive.js b/src-docs/src/views/responsive/responsive.js new file mode 100644 index 00000000000..82e42893d4a --- /dev/null +++ b/src-docs/src/views/responsive/responsive.js @@ -0,0 +1,46 @@ +import React from 'react'; + +import { + EuiCode, + EuiHideFrom, + EuiShowFor, +} from '../../../../src/components'; + +export default () => ( +
+ + Hiding from xs screens only + +
+ + Hiding from xs, s screens + +
+ + Hiding from xs, s, m screens + +
+ + Hiding from l screens only + + +
+
+ + + Showing for xs screens only + +
+ + Showing for xs, s screens + +
+ + Showing for xs, s, m screens + +
+ + Showing for l screen only + +
+); diff --git a/src-docs/src/views/responsive/responsive_example.js b/src-docs/src/views/responsive/responsive_example.js new file mode 100644 index 00000000000..76a983c20bf --- /dev/null +++ b/src-docs/src/views/responsive/responsive_example.js @@ -0,0 +1,40 @@ +import React from 'react'; + +import { renderToHtml } from '../../services'; + +import { + GuideSectionTypes, +} from '../../components'; + +import { + EuiCode, + EuiShowFor, + EuiHideFrom, +} from '../../../../src/components'; + +import Responsive from './responsive'; +const responsiveSource = require('!!raw-loader!./responsive'); +const responsiveHtml = renderToHtml(Responsive); + +export const ResponsiveExample = { + title: 'Responsive', + sections: [{ + title: 'EuiShowFor and EuiHideFrom', + source: [{ + type: GuideSectionTypes.JS, + code: responsiveSource, + }, { + type: GuideSectionTypes.HTML, + code: responsiveHtml, + }], + text: ( +

+ Pass an array of screen widths [xs, s, m, l] to either + the EuiShowFor or EuiHideFrom components + to make them responsive. +

+ ), + props: { EuiShowFor, EuiHideFrom }, + demo: , + }], +}; diff --git a/src-docs/src/views/utility_classes/utility_classes.js b/src-docs/src/views/utility_classes/utility_classes.js index f4aad5ed3e5..c0cfa828e02 100644 --- a/src-docs/src/views/utility_classes/utility_classes.js +++ b/src-docs/src/views/utility_classes/utility_classes.js @@ -93,5 +93,26 @@ export default () => ( .eui-displayInlineBlock +

Responsive

+ + .euiHideFrom--xsmall + + .euiHideFrom--small + + .euiHideFrom--medium + + .euiHideFrom--large + + + + .euiShowFor--xsmall + + .euiShowFor--small + + .euiShowFor--medium + + .euiShowFor--large + + ); diff --git a/src/components/index.js b/src/components/index.js index 9b6ca6ccd9d..e50b15277eb 100644 --- a/src/components/index.js +++ b/src/components/index.js @@ -307,3 +307,9 @@ export { EuiIconTip, EuiToolTip, } from './tool_tip'; + +export { + EuiHideFrom, + EuiShowFor, +} from './responsive'; + diff --git a/src/components/responsive/__snapshots__/hide_from.test.js.snap b/src/components/responsive/__snapshots__/hide_from.test.js.snap new file mode 100644 index 00000000000..ac326d4f16e --- /dev/null +++ b/src/components/responsive/__snapshots__/hide_from.test.js.snap @@ -0,0 +1,9 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`EuiHideFrom is rendered 1`] = ` + +`; diff --git a/src/components/responsive/__snapshots__/show_for.test.js.snap b/src/components/responsive/__snapshots__/show_for.test.js.snap new file mode 100644 index 00000000000..11ef1c5dba4 --- /dev/null +++ b/src/components/responsive/__snapshots__/show_for.test.js.snap @@ -0,0 +1,9 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`EuiShowFor is rendered 1`] = ` + +`; diff --git a/src/components/responsive/hide_from.js b/src/components/responsive/hide_from.js new file mode 100644 index 00000000000..65a444f6b48 --- /dev/null +++ b/src/components/responsive/hide_from.js @@ -0,0 +1,48 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import classNames from 'classnames'; + +const responsiveSizesToClassNameMap = { + xs: 'euiHideFrom--xsmall', + s: 'euiHideFrom--small', + m: 'euiHideFrom--medium', + l: 'euiHideFrom--large', +} + +const RESPONSIVE_SIZES = Object.keys(responsiveSizesToClassNameMap); + +export const EuiHideFrom = ({ + children, + className, + sizes, + ...rest, +}) => { + + const sizingClasses = sizes.map(function(item){ + return responsiveSizesToClassNameMap[item]; + }); + + const classes = classNames( + 'euiHideFrom', + sizingClasses, + className + ); + + return ( + + {children} + + ); +}; + +EuiHideFrom.propTypes = { + children: PropTypes.node, + className: PropTypes.string, + /** + * List of all the responsive sizes to hide the children from + */ + sizes: PropTypes.arrayOf(PropTypes.oneOf(RESPONSIVE_SIZES)).isRequired, +}; diff --git a/src/components/responsive/hide_from.test.js b/src/components/responsive/hide_from.test.js new file mode 100644 index 00000000000..040d44df8ce --- /dev/null +++ b/src/components/responsive/hide_from.test.js @@ -0,0 +1,16 @@ +import React from 'react'; +import { render } from 'enzyme'; +import { requiredProps } from '../../test'; + +import { EuiHideFrom } from './hide_from'; + +describe('EuiHideFrom', () => { + test('is rendered', () => { + const component = render( + + ); + + expect(component) + .toMatchSnapshot(); + }); +}); diff --git a/src/components/responsive/index.js b/src/components/responsive/index.js new file mode 100644 index 00000000000..406aa05c4c5 --- /dev/null +++ b/src/components/responsive/index.js @@ -0,0 +1,7 @@ +export { + EuiHideFrom, +} from './hide_from'; + +export { + EuiShowFor, +} from './show_for'; diff --git a/src/components/responsive/show_for.js b/src/components/responsive/show_for.js new file mode 100644 index 00000000000..84755f14687 --- /dev/null +++ b/src/components/responsive/show_for.js @@ -0,0 +1,48 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import classNames from 'classnames'; + +const responsiveSizesToClassNameMap = { + xs: 'euiShowFor--xsmall', + s: 'euiShowFor--small', + m: 'euiShowFor--medium', + l: 'euiShowFor--large', +} + +const RESPONSIVE_SIZES = Object.keys(responsiveSizesToClassNameMap); + +export const EuiShowFor = ({ + children, + className, + sizes, + ...rest, +}) => { + + const sizingClasses = sizes.map(function(item){ + return responsiveSizesToClassNameMap[item]; + }); + + const classes = classNames( + 'euiShowFor', + sizingClasses, + className + ); + + return ( + + {children} + + ); +}; + +EuiShowFor.propTypes = { + children: PropTypes.node, + className: PropTypes.string, + /** + * List of all the responsive sizes to show the children for + */ + sizes: PropTypes.arrayOf(PropTypes.oneOf(RESPONSIVE_SIZES)).isRequired, +}; diff --git a/src/components/responsive/show_for.test.js b/src/components/responsive/show_for.test.js new file mode 100644 index 00000000000..edad9610caa --- /dev/null +++ b/src/components/responsive/show_for.test.js @@ -0,0 +1,16 @@ +import React from 'react'; +import { render } from 'enzyme'; +import { requiredProps } from '../../test'; + +import { EuiShowFor } from './show_for'; + +describe('EuiShowFor', () => { + test('is rendered', () => { + const component = render( + + ); + + expect(component) + .toMatchSnapshot(); + }); +}); diff --git a/src/global_styling/utility/_utility.scss b/src/global_styling/utility/_utility.scss index c3bef018aef..98d360f494e 100644 --- a/src/global_styling/utility/_utility.scss +++ b/src/global_styling/utility/_utility.scss @@ -40,3 +40,39 @@ white-space: nowrap !important; word-wrap: normal !important; /* 2 */ } + +/** + * Responsive + * + * 3. Be sure to hide/show the element initially + */ +[class*="euiHideFrom"] { + display: initial !important; /* 3 */ +} +[class*="euiShowFor"] { + display: none !important; /* 3 */ +} +.euiHideFrom--xsmall { + @include screenXSmall() { display: none !important; } +} +.euiHideFrom--small { + @include screenSmall() { display: none !important; } +} +.euiHideFrom--medium { + @include screenMedium() { display: none !important; } +} +.euiHideFrom--large { + @include screenLarge() { display: none !important; } +} +.euiShowFor--xsmall { + @include screenXSmall() { display: initial !important; } +} +.euiShowFor--small { + @include screenSmall() { display: initial !important; } +} +.euiShowFor--medium { + @include screenMedium() { display: initial !important; } +} +.euiShowFor--large { + @include screenLarge() { display: initial !important; } +}