diff --git a/CHANGELOG.md b/CHANGELOG.md index f47bf8b1bfe..1e903271216 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,6 @@ # [`master`](https://github.com/elastic/eui/tree/master) +- Added `EuiSteps` component - Added `EuiHealth` components for status checks [(#158)](https://github.com/elastic/eui/pull/158) - Cleaned up styling for checkboxes, switches, and radios [(#158)](https://github.com/elastic/eui/pull/158) - Form `disabled` states are now more consistant [(#158)](https://github.com/elastic/eui/pull/158) @@ -51,3 +52,5 @@ # [`0.0.1`](https://github.com/elastic/eui/tree/v0.0.1) Initial Release - Initial public release + + diff --git a/src-docs/src/services/routes/routes.js b/src-docs/src/services/routes/routes.js index 4970ea61e65..7aa6bfc6069 100644 --- a/src-docs/src/services/routes/routes.js +++ b/src-docs/src/services/routes/routes.js @@ -109,6 +109,9 @@ import { SideNavExample } import { SpacerExample } from '../../views/spacer/spacer_example'; +import { StepsExample } + from '../../views/steps/steps_example'; + import { TableExample } from '../../views/table/table_example'; @@ -200,6 +203,7 @@ const components = [ ProgressExample, SideNavExample, SpacerExample, + StepsExample, TableExample, TabsExample, TextExample, diff --git a/src-docs/src/views/steps/heading_element_steps.js b/src-docs/src/views/steps/heading_element_steps.js new file mode 100644 index 00000000000..062678814ed --- /dev/null +++ b/src-docs/src/views/steps/heading_element_steps.js @@ -0,0 +1,22 @@ +import React from 'react'; + +import { + EuiSteps, +} from '../../../../src/components'; + +const steps = [ + { + title: 'inspect me', + children:

Did you notice the step title is inside a Heading 2 element?

+ } +]; + +export default () => ( +
+

Heading 1

+ +
+); diff --git a/src-docs/src/views/steps/steps.js b/src-docs/src/views/steps/steps.js new file mode 100644 index 00000000000..167d7cefb66 --- /dev/null +++ b/src-docs/src/views/steps/steps.js @@ -0,0 +1,59 @@ +import React from 'react'; + +import { + EuiCode, + EuiSpacer, + EuiSteps, + EuiText, +} from '../../../../src/components'; + +const firstSetOfSteps = [ + { + title: 'step 1', + children:

Do this first

+ }, + { + title: 'step 2', + children:

Then this

+ }, + { + title: 'step 3', + children:

And finally, do this

+ }, +]; + +const nextSetOfSteps = [ + { + title: 'good step', + children:

Do this first

+ }, + { + title: 'better step', + children:

Then this

+ }, + { + title: 'best step', + children:

And finally, do this

+ }, +]; + +export default () => ( +
+ + + + +

+ Set firstStepNumber to continue step numbering after any type of break in the content +

+ +
+ + +
+); diff --git a/src-docs/src/views/steps/steps_example.js b/src-docs/src/views/steps/steps_example.js new file mode 100644 index 00000000000..9a89578965b --- /dev/null +++ b/src-docs/src/views/steps/steps_example.js @@ -0,0 +1,51 @@ +import React from 'react'; + +import { renderToHtml } from '../../services'; + +import { + GuideSectionTypes, +} from '../../components'; + +import Steps from './steps'; +const stepsSource = require('!!raw-loader!./steps'); +const stepsHtml = renderToHtml(Steps); + +import HeadingElementSteps from './heading_element_steps'; +const headingElementStepsSource = require('!!raw-loader!./heading_element_steps'); +const headingElementStepsHtml = renderToHtml(HeadingElementSteps); + +export const StepsExample = { + title: 'Steps', + sections: [{ + title: 'Steps', + source: [{ + type: GuideSectionTypes.JS, + code: stepsSource, + }, { + type: GuideSectionTypes.HTML, + code: stepsHtml, + }], + text: ( +

+ Numbered steps +

+ ), + demo: , + }, + { + title: 'Heading Element Steps', + source: [{ + type: GuideSectionTypes.JS, + code: headingElementStepsSource, + }, { + type: GuideSectionTypes.HTML, + code: headingElementStepsHtml, + }], + text: ( +

+ something something better accessibility +

+ ), + demo: , + }], +}; diff --git a/src/components/index.js b/src/components/index.js index cc0db64f9f1..3f512fe7c6c 100644 --- a/src/components/index.js +++ b/src/components/index.js @@ -174,6 +174,10 @@ export { EuiSpacer, } from './spacer'; +export { + EuiSteps, +} from './steps'; + export { EuiTable, EuiTableBody, diff --git a/src/components/index.scss b/src/components/index.scss index d794e289452..b538506c0ad 100644 --- a/src/components/index.scss +++ b/src/components/index.scss @@ -30,6 +30,7 @@ @import 'progress/index'; @import 'side_nav/index'; @import 'spacer/index'; +@import 'steps/index'; @import 'table/index'; @import 'tabs/index'; @import 'title/index'; diff --git a/src/components/steps/__snapshots__/step.test.js.snap b/src/components/steps/__snapshots__/step.test.js.snap new file mode 100644 index 00000000000..71be26248e2 --- /dev/null +++ b/src/components/steps/__snapshots__/step.test.js.snap @@ -0,0 +1,29 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`EuiStep is rendered 1`] = ` +
+
+
+ 1 +
+

+ First step +

+
+
+

+ Do this +

+
+
+`; diff --git a/src/components/steps/__snapshots__/steps.test.js.snap b/src/components/steps/__snapshots__/steps.test.js.snap new file mode 100644 index 00000000000..326cd6ed371 --- /dev/null +++ b/src/components/steps/__snapshots__/steps.test.js.snap @@ -0,0 +1,235 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`EuiSteps renders step title inside "headingElement" element 1`] = ` +
+
+
+
+ 1 +
+

+ first title +

+
+
+

+ Do this first +

+
+
+
+
+
+ 2 +
+

+ second title +

+
+
+

+ Then this +

+
+
+
+
+
+ 3 +
+

+ third title +

+
+
+

+ And finally, do this +

+
+
+
+`; + +exports[`EuiSteps renders steps 1`] = ` +
+
+
+
+ 1 +
+

+ first title +

+
+
+

+ Do this first +

+
+
+
+
+
+ 2 +
+

+ second title +

+
+
+

+ Then this +

+
+
+
+
+
+ 3 +
+

+ third title +

+
+
+

+ And finally, do this +

+
+
+
+`; + +exports[`EuiSteps renders steps with firstStepNumber 1`] = ` +
+
+
+
+ 10 +
+

+ first title +

+
+
+

+ Do this first +

+
+
+
+
+
+ 11 +
+

+ second title +

+
+
+

+ Then this +

+
+
+
+
+
+ 12 +
+

+ third title +

+
+
+

+ And finally, do this +

+
+
+
+`; diff --git a/src/components/steps/_index.scss b/src/components/steps/_index.scss new file mode 100644 index 00000000000..c64a8f5a532 --- /dev/null +++ b/src/components/steps/_index.scss @@ -0,0 +1 @@ +@import 'steps'; diff --git a/src/components/steps/_steps.scss b/src/components/steps/_steps.scss new file mode 100644 index 00000000000..51c571ab08a --- /dev/null +++ b/src/components/steps/_steps.scss @@ -0,0 +1,27 @@ +.euiSteps { + +} + +.euiStepNumber { + width: 32px; + height: 32px; + display: inline-block; + line-height: 32px; + text-align: center; + color: #FFF; + border-radius: 100%; + background-color: #0079a5; +} + +.euiStepTitle { + display: inline-block; + margin-left: 16px; +} + +.euiStepContent { + border-left: medium solid #D9D9D9; + margin-top: 8px; + margin-bottom: 8px; + margin-left: 16px; + padding-left: 24px; +} diff --git a/src/components/steps/index.js b/src/components/steps/index.js new file mode 100644 index 00000000000..c197c4f0b27 --- /dev/null +++ b/src/components/steps/index.js @@ -0,0 +1,3 @@ +export { + EuiSteps, +} from './steps'; diff --git a/src/components/steps/step.js b/src/components/steps/step.js new file mode 100644 index 00000000000..b59d78e526f --- /dev/null +++ b/src/components/steps/step.js @@ -0,0 +1,46 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import classNames from 'classnames'; + +import { + EuiTitle +} from '../title'; + +export const EuiStep = ({ + className, + children, + headingElement, + step, + title, + ...rest +}) => { + const classes = classNames('euiStep', className); + return ( +
+ +
+
+ {step} +
+ + {React.createElement(headingElement, null, title)} + +
+ +
+ {children} +
+ +
+ ); +}; + +EuiStep.propTypes = { + children: PropTypes.node.isRequired, + step: PropTypes.number.isRequired, + title: PropTypes.string.isRequired, + headingElement: PropTypes.string.isRequired, +}; diff --git a/src/components/steps/step.test.js b/src/components/steps/step.test.js new file mode 100644 index 00000000000..3393d03e6eb --- /dev/null +++ b/src/components/steps/step.test.js @@ -0,0 +1,23 @@ +import React from 'react'; +import { render } from 'enzyme'; +import { requiredProps } from '../../test/required_props'; + +import { EuiStep } from './step'; + +describe('EuiStep', () => { + test('is rendered', () => { + const stepContent = (

Do this

); + const component = render( + + ); + + expect(component) + .toMatchSnapshot(); + }); +}); diff --git a/src/components/steps/steps.js b/src/components/steps/steps.js new file mode 100644 index 00000000000..e888f90c202 --- /dev/null +++ b/src/components/steps/steps.js @@ -0,0 +1,64 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import classNames from 'classnames'; +import { EuiStep } from './step'; + +function renderSteps(steps, firstStepNumber, headingElement) { + return steps.map((step, index) => { + const { + className, + children, + title, + ...rest + } = step; + + return ( + + {children} + + ); + }); +} + +export const EuiSteps = ({ + className, + firstStepNumber, + headingElement, + steps, + ...rest, +}) => { + const classes = classNames('euiSteps', className); + + return ( +
+ {renderSteps(steps, firstStepNumber, headingElement)} +
+ ); +}; + +const stepPropType = PropTypes.shape({ + title: PropTypes.string.isRequired, + children: PropTypes.node +}); + +EuiSteps.propTypes = { + className: PropTypes.string, + firstStepNumber: PropTypes.number, + headingElement: PropTypes.string, + steps: PropTypes.arrayOf(stepPropType).isRequired, +}; + +EuiSteps.defaultProps = { + firstStepNumber: 1, + headingElement: 'p' +}; diff --git a/src/components/steps/steps.test.js b/src/components/steps/steps.test.js new file mode 100644 index 00000000000..4afb3ee40f4 --- /dev/null +++ b/src/components/steps/steps.test.js @@ -0,0 +1,49 @@ +import React from 'react'; +import { render } from 'enzyme'; +import { requiredProps } from '../../test/required_props'; + +import { EuiSteps } from './steps'; + +const steps = [ + { + title: 'first title', + children:

Do this first

+ }, + { + title: 'second title', + children:

Then this

+ }, + { + title: 'third title', + children:

And finally, do this

+ }, +]; + +describe('EuiSteps', () => { + test('renders steps', () => { + const component = render( + + ); + + expect(component) + .toMatchSnapshot(); + }); + + test('renders steps with firstStepNumber', () => { + const component = render( + + ); + + expect(component) + .toMatchSnapshot(); + }); + + test('renders step title inside "headingElement" element', () => { + const component = render( + + ); + + expect(component) + .toMatchSnapshot(); + }); +});