From 079566ed5c29d8a5a69ae8e97aa337afec378907 Mon Sep 17 00:00:00 2001 From: CJ Cenizal Date: Thu, 10 May 2018 11:04:01 -0700 Subject: [PATCH] Add EuiBreadcrumbs. --- CHANGELOG.md | 3 +- src-docs/src/routes.js | 4 + src-docs/src/views/breadcrumbs/breadcrumbs.js | 49 ++++++++++ .../views/breadcrumbs/breadcrumbs_example.js | 38 ++++++++ .../__snapshots__/breadcrumbs.test.js.snap | 94 +++++++++++++++++++ src/components/breadcrumbs/_breadcrumbs.scss | 20 ++++ src/components/breadcrumbs/_index.scss | 3 + src/components/breadcrumbs/breadcrumbs.js | 79 ++++++++++++++++ .../breadcrumbs/breadcrumbs.test.js | 33 +++++++ src/components/breadcrumbs/index.js | 3 + src/components/index.js | 18 ++-- src/components/index.scss | 1 + src/components/link/link.js | 3 + 13 files changed, 340 insertions(+), 8 deletions(-) create mode 100644 src-docs/src/views/breadcrumbs/breadcrumbs.js create mode 100644 src-docs/src/views/breadcrumbs/breadcrumbs_example.js create mode 100644 src/components/breadcrumbs/__snapshots__/breadcrumbs.test.js.snap create mode 100644 src/components/breadcrumbs/_breadcrumbs.scss create mode 100644 src/components/breadcrumbs/_index.scss create mode 100644 src/components/breadcrumbs/breadcrumbs.js create mode 100644 src/components/breadcrumbs/breadcrumbs.test.js create mode 100644 src/components/breadcrumbs/index.js diff --git a/CHANGELOG.md b/CHANGELOG.md index 7972930e30b4..0c1c5a4dd114 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ ## [`master`](https://github.com/elastic/eui/tree/master) -- Added utility CSS classes for text and alignment concerns. ([#774](https://github.com/elastic/eui/pull/774)) +- Added utility CSS classes for text and alignment concerns ([#774](https://github.com/elastic/eui/pull/774)) +- Added `EuiBreadcrumbs` ([#815](https://github.com/elastic/eui/pull/815)) **Bug fixes** diff --git a/src-docs/src/routes.js b/src-docs/src/routes.js index bde014ec8a9e..2c6b734d8be0 100644 --- a/src-docs/src/routes.js +++ b/src-docs/src/routes.js @@ -60,6 +60,9 @@ import { BadgeExample } import { BottomBarExample } from './views/bottom_bar/bottom_bar_example'; +import { BreadcrumbsExample } + from './views/breadcrumbs/breadcrumbs_example'; + import { ButtonExample } from './views/button/button_example'; @@ -286,6 +289,7 @@ const navigation = [{ }, { name: 'Navigation', items: [ + BreadcrumbsExample, ButtonExample, ContextMenuExample, KeyPadMenuExample, diff --git a/src-docs/src/views/breadcrumbs/breadcrumbs.js b/src-docs/src/views/breadcrumbs/breadcrumbs.js new file mode 100644 index 000000000000..d2db2028b9b7 --- /dev/null +++ b/src-docs/src/views/breadcrumbs/breadcrumbs.js @@ -0,0 +1,49 @@ +import React, { Fragment } from 'react'; + +import { + EuiBreadcrumbs, + EuiButton, + EuiPageContentHeader, + EuiPageContentHeaderSection, + EuiTitle, + EuiSpacer, +} from '../../../../src/components'; + +export default () => { + const breadcrumbs = [{ + text: 'Animals', + href: '#', + onClick: (e) => { e.preventDefault(); console.log('You clicked Animals'); }, + 'data-test-subj': 'breadcrumbsAnimals', + className: 'customClass', + }, { + text: 'Reptiles', + href: '#', + onClick: (e) => { e.preventDefault(); console.log('You clicked Reptiles'); }, + }, { + text: 'Boa constrictor', + href: '#', + onClick: (e) => { e.preventDefault(); console.log('You clicked Boa constrictor'); }, + }, { + text: 'Edit', + }]; + + return ( + + + + + + + +

Boa constrictor

+
+
+ + + Cancel + +
+
+ ); +}; diff --git a/src-docs/src/views/breadcrumbs/breadcrumbs_example.js b/src-docs/src/views/breadcrumbs/breadcrumbs_example.js new file mode 100644 index 000000000000..e3e2121ffd64 --- /dev/null +++ b/src-docs/src/views/breadcrumbs/breadcrumbs_example.js @@ -0,0 +1,38 @@ +import React from 'react'; + +import { renderToHtml } from '../../services'; + +import { + GuideSectionTypes, +} from '../../components'; + +import { + EuiCode, + EuiBreadcrumbs, +} from '../../../../src/components'; + +import Breadcrumbs from './breadcrumbs'; +const breadcrumbsSource = require('!!raw-loader!./breadcrumbs'); +const breadcrumbsHtml = renderToHtml(Breadcrumbs); + +export const BreadcrumbsExample = { + title: 'Breadcrumbs', + sections: [{ + source: [{ + type: GuideSectionTypes.JS, + code: breadcrumbsSource, + }, { + type: GuideSectionTypes.HTML, + code: breadcrumbsHtml, + }], + text: ( +

+ EuiBreadcrumbs let the user track their progress within and back out of + a UX flow. They work well within EuiPageContentHeader but be careful + not to be use them within an app that also uses EuiHeaderBreadcrumbs. +

+ ), + props: { EuiBreadcrumbs }, + demo: , + }], +}; diff --git a/src/components/breadcrumbs/__snapshots__/breadcrumbs.test.js.snap b/src/components/breadcrumbs/__snapshots__/breadcrumbs.test.js.snap new file mode 100644 index 000000000000..7226d1413b4b --- /dev/null +++ b/src/components/breadcrumbs/__snapshots__/breadcrumbs.test.js.snap @@ -0,0 +1,94 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`EuiBreadcrumbs is rendered 1`] = ` +
+ + Animals + + + + + + + + + Reptiles + + + + + + + + + Boa constrictor + + + + + + + + + Edit + +
+`; diff --git a/src/components/breadcrumbs/_breadcrumbs.scss b/src/components/breadcrumbs/_breadcrumbs.scss new file mode 100644 index 000000000000..3205a19e4aa9 --- /dev/null +++ b/src/components/breadcrumbs/_breadcrumbs.scss @@ -0,0 +1,20 @@ +.euiBreadcrumbs { + font-size: $euiFontSizeS; +} + +.euiBreadcrumb { + display: inline-block; + + &:not(.euiBreadcrumb--last) { + margin-right: $euiBreadcrumbSpacing; + } +} + +.euiBreadcrumb--last { + font-weight: 500; +} + +.euiBreadcrumbArrow { + margin-right: $euiBreadcrumbSpacing; + transform: translateY(-0.1em); +} diff --git a/src/components/breadcrumbs/_index.scss b/src/components/breadcrumbs/_index.scss new file mode 100644 index 000000000000..d4d56ed0d568 --- /dev/null +++ b/src/components/breadcrumbs/_index.scss @@ -0,0 +1,3 @@ +$euiBreadcrumbSpacing: $euiSizeXS; + +@import 'breadcrumbs'; diff --git a/src/components/breadcrumbs/breadcrumbs.js b/src/components/breadcrumbs/breadcrumbs.js new file mode 100644 index 000000000000..01148f46af57 --- /dev/null +++ b/src/components/breadcrumbs/breadcrumbs.js @@ -0,0 +1,79 @@ +import React, { Fragment } from 'react'; +import PropTypes from 'prop-types'; +import classNames from 'classnames'; + +import { EuiIcon } from '../icon'; +import { EuiLink } from '../link'; + +export const EuiBreadcrumbs = ({ + breadcrumbs, + className, + ...rest, +}) => { + const breadcrumbElements = breadcrumbs.map((breadcrumb, index) => { + const { + text, + href, + onClick, + ...breadcrumbRest + } = breadcrumb; + + const isLastBreadcrumb = index === breadcrumbs.length - 1; + + const breadcrumbClasses = classNames('euiBreadcrumb', { + 'euiBreadcrumb--last': isLastBreadcrumb, + }); + + let link; + + if (isLastBreadcrumb) { + link = ( + + { text } + + ); + } else { + link = ( + + {text} + + ); + } + + let arrow; + + if (!isLastBreadcrumb) { + arrow = ; + } + + return ( + + {link} + {arrow} + + ); + }) + + const classes = classNames('euiBreadcrumbs', className); + + return ( +
+ {breadcrumbElements} +
+ ); +}; + +EuiBreadcrumbs.propTypes = { + className: PropTypes.string, + breadcrumbs: PropTypes.arrayOf(PropTypes.shape({ + text: PropTypes.node.isRequired, + href: PropTypes.string, + onClick: PropTypes.func, + })).isRequired, +}; diff --git a/src/components/breadcrumbs/breadcrumbs.test.js b/src/components/breadcrumbs/breadcrumbs.test.js new file mode 100644 index 000000000000..49933c1c007a --- /dev/null +++ b/src/components/breadcrumbs/breadcrumbs.test.js @@ -0,0 +1,33 @@ +import React from 'react'; +import { render } from 'enzyme'; +import { requiredProps } from '../../test'; + +import { EuiBreadcrumbs } from './breadcrumbs'; + +describe('EuiBreadcrumbs', () => { + const breadcrumbs = [{ + text: 'Animals', + href: '#', + onClick: (e) => { e.preventDefault(); console.log('You clicked Animals'); }, + 'data-test-subj': 'breadcrumbsAnimals', + className: 'customClass', + }, { + text: 'Reptiles', + href: '#', + onClick: (e) => { e.preventDefault(); console.log('You clicked Reptiles'); }, + }, { + text: 'Boa constrictor', + href: '#', + onClick: (e) => { e.preventDefault(); console.log('You clicked Boa constrictor'); }, + }, { + text: 'Edit', + }]; + + test('is rendered', () => { + const component = render( + + ); + + expect(component).toMatchSnapshot(); + }); +}); diff --git a/src/components/breadcrumbs/index.js b/src/components/breadcrumbs/index.js new file mode 100644 index 000000000000..35a6bb68c4cb --- /dev/null +++ b/src/components/breadcrumbs/index.js @@ -0,0 +1,3 @@ +export { + EuiBreadcrumbs, +} from './breadcrumbs'; diff --git a/src/components/index.js b/src/components/index.js index cb9863e38fa2..9734eba0acec 100644 --- a/src/components/index.js +++ b/src/components/index.js @@ -11,10 +11,19 @@ export { EuiScreenReaderOnly, } from './accessibility'; +export { + EuiBadge, + EuiBetaBadge, +} from './badge'; + export { EuiBottomBar, } from './bottom_bar'; +export { + EuiBreadcrumbs, +} from './breadcrumbs'; + export { EuiButton, EuiButtonEmpty, @@ -22,18 +31,13 @@ export { } from './button'; export { - EuiBadge, - EuiBetaBadge, -} from './badge'; + EuiCallOut, +} from './call_out'; export { EuiCard, } from './card'; -export { - EuiCallOut, -} from './call_out'; - export { EuiCode, EuiCodeBlock, diff --git a/src/components/index.scss b/src/components/index.scss index e736d0d2340c..cb290518e8e0 100644 --- a/src/components/index.scss +++ b/src/components/index.scss @@ -8,6 +8,7 @@ @import 'basic_table/index'; @import 'bottom_bar/index'; @import 'button/index'; +@import 'breadcrumbs/index'; @import 'call_out/index'; @import 'card/index'; @import 'code/index'; diff --git a/src/components/link/link.js b/src/components/link/link.js index cee3b79cd5f9..573041a49621 100644 --- a/src/components/link/link.js +++ b/src/components/link/link.js @@ -24,6 +24,7 @@ export const EuiLink = ({ target, rel, type, + onClick, ...rest }) => { const classes = classNames('euiLink', colorsToClassNameMap[color], className); @@ -33,6 +34,7 @@ export const EuiLink = ({