diff --git a/components/component-docs.json b/components/component-docs.json index 9895f29c76..f38f88616b 100644 --- a/components/component-docs.json +++ b/components/component-docs.json @@ -10948,7 +10948,129 @@ "SLDS-component-path": "/components/progress-indicator", "dependencies": [] }, - "progress-ring": { + "progress-bar": { + "description": "A progress bar component communicates to the user the progress of a particular process.", + "methods": [ + { + "name": "getId", + "docblock": "Get the progress bar's HTML id. Generate a new one if no ID present.", + "modifiers": [], + "params": [], + "returns": null, + "description": "Get the progress bars's HTML id. Generate a new one if no ID present." + }, + { + "name": "getDescription", + "docblock": "Get the the description for progress bar. Doesn't show description if label is not given.", + "modifiers": [], + "params": [], + "returns": { + "description": "Progress Bar Description Container", + "type": { + "name": "string" + } + }, + "description": "Get the the description for progress bar. Doesn't show description if label is not given." + } + ], + "props": { + "id": { + "type": { + "name": "string" + }, + "required": false, + "description": "HTML id for component." + }, + "className": { + "type": { + "name": "union", + "value": [ + { + "name": "array" + }, + { + "name": "object" + }, + { + "name": "string" + } + ] + }, + "required": false, + "description": "CSS classes to be added to tag with `.slds-progress-bar`. Uses `classNames` [API](https://github.com/JedWatson/classnames)." + }, + "label": { + "type": { + "name": "string" + }, + "required": false, + "description": "Label for the progress bar." + }, + "radius": { + "type": { + "name": "enum", + "value": [ + { + "value": "'circular'", + "computed": false + } + ] + }, + "required": false, + "description": "Border radius of Progress Bar." + }, + "color": { + "type": { + "name": "enum", + "value": [ + { + "value": "'success'", + "computed": false + } + ] + }, + "required": false, + "description": "Color for filling the progress bar" + }, + "thickness": { + "type": { + "name": "enum", + "value": [ + { + "value": "'x-small'", + "computed": false + }, + { + "value": "'small'", + "computed": false + }, + { + "value": "'medium'", + "computed": false + }, + { + "value": "'large'", + "computed": false + } + ] + }, + "required": false, + "description": "Thickness of the progress bar" + }, + "value": { + "type": { + "name": "number" + }, + "required": true, + "description": "Percentage of progress completion, ranging [0, 100]." + } + }, + "route": "progress-bars", + "display-name": "Progress Bars", + "SLDS-component-path": "/components/progress-bar", + "dependencies": [] + }, + "progress-ring": { "description": "Customizable and configurable progress ring. Will display progress in a circular progress bar factor, and is capable of displaying iconography inside of the ring structure.", "methods": [ { diff --git a/components/index.js b/components/index.js index 427d9668f3..35bcae411c 100644 --- a/components/index.js +++ b/components/index.js @@ -218,6 +218,9 @@ export PopoverTooltip from './tooltip'; export SLDSTooltip from './tooltip'; export Tooltip from './tooltip'; +export SLDSProgressBar from './progress-bar'; +export ProgressBar from './progress-bar'; + export SLDSProgressIndicator from './progress-indicator'; export ProgressIndicator from './progress-indicator'; diff --git a/components/progress-bar/__docs__/__snapshots__/storybook-stories.storyshot b/components/progress-bar/__docs__/__snapshots__/storybook-stories.storyshot new file mode 100644 index 0000000000..f5dc2fd7b5 --- /dev/null +++ b/components/progress-bar/__docs__/__snapshots__/storybook-stories.storyshot @@ -0,0 +1,275 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`DOM snapshots SLDSProgressBar Color 1`] = ` +
+
+ + Color: success + +
+ +
+ + + Progress: + 75% + + +
+
+
+
+`; + +exports[`DOM snapshots SLDSProgressBar Default 1`] = ` +
+
+
+ +
+ + + Progress: + 75% + + +
+
+
+
+`; + +exports[`DOM snapshots SLDSProgressBar Descriptive 1`] = ` +
+
+
+
+ + Einstein Setup Assistant + + +
+
+ + + Progress: + 90% + + +
+
+
+
+`; + +exports[`DOM snapshots SLDSProgressBar Radius 1`] = ` +
+
+ + Radius: circular + +
+ +
+ + + Progress: + 75% + + +
+
+
+
+`; + +exports[`DOM snapshots SLDSProgressBar Thickness 1`] = ` +
+
+ + Thickness: x-small + +
+ +
+ + + Progress: + 90% + + +
+
+
+ + Thickness: small + +
+ +
+ + + Progress: + 75% + + +
+
+
+ + Thickness: medium + +
+ +
+ + + Progress: + 50% + + +
+
+
+ + Thickness: large + +
+ +
+ + + Progress: + 25% + + +
+
+
+
+`; diff --git a/components/progress-bar/__docs__/site-stories.js b/components/progress-bar/__docs__/site-stories.js new file mode 100644 index 0000000000..e2bdce861f --- /dev/null +++ b/components/progress-bar/__docs__/site-stories.js @@ -0,0 +1,14 @@ +// This object is imported into the documentation site. An example for the documentation site should be part of the pull request for the component. The object key is the kabob case of the "URL folder". In the case of `http://localhost:8080/components/app-launcher/`, `app-launcher` is the `key`. The folder name is created by `components.component` value in `package.json`. The following uses webpack's raw-loader plugin to get "text files" that will be eval()'d by CodeMirror within the documentation site on page load. + +/* eslint-env node */ +/* eslint-disable global-require */ + +const siteStories = [ + require('raw-loader!@salesforce/design-system-react/components/progress-bar/__examples__/default.jsx'), + require('raw-loader!@salesforce/design-system-react/components/progress-bar/__examples__/descriptive.jsx'), + require('raw-loader!@salesforce/design-system-react/components/progress-bar/__examples__/color.jsx'), + require('raw-loader!@salesforce/design-system-react/components/progress-bar/__examples__/radius.jsx'), + require('raw-loader!@salesforce/design-system-react/components/progress-bar/__examples__/thickness.jsx'), +]; + +module.exports = siteStories; diff --git a/components/progress-bar/__docs__/storybook-stories.jsx b/components/progress-bar/__docs__/storybook-stories.jsx new file mode 100644 index 0000000000..e1f157d805 --- /dev/null +++ b/components/progress-bar/__docs__/storybook-stories.jsx @@ -0,0 +1,18 @@ +import React from 'react'; +import { storiesOf } from '@storybook/react'; +import { PROGRESS_BAR } from '../../../utilities/constants'; +import Default from '../__examples__/default'; +import Thickness from '../__examples__/thickness'; +import Color from '../__examples__/color'; +import Radius from '../__examples__/radius'; +import Descriptive from '../__examples__/descriptive'; + +storiesOf(PROGRESS_BAR, module) + .addDecorator((getStory) => ( +
{getStory()}
+ )) + .add('Default', () => ) + .add('Descriptive', () => ) + .add('Color', () => ) + .add('Radius', () => ) + .add('Thickness', () => ); diff --git a/components/progress-bar/__examples__/color.jsx b/components/progress-bar/__examples__/color.jsx new file mode 100644 index 0000000000..7c7cc20871 --- /dev/null +++ b/components/progress-bar/__examples__/color.jsx @@ -0,0 +1,16 @@ +import React from 'react'; +import ProgressBar from '~/components/progress-bar'; + +class Example extends React.Component { + render() { + return ( +
+ Color: success + +
+ ); + } +} +Example.displayName = 'ProgressBarColor'; + +export default Example; // export is replaced with `ReactDOM.render(, mountNode);` at runtime diff --git a/components/progress-bar/__examples__/default.jsx b/components/progress-bar/__examples__/default.jsx new file mode 100644 index 0000000000..ac20247875 --- /dev/null +++ b/components/progress-bar/__examples__/default.jsx @@ -0,0 +1,15 @@ +import React from 'react'; +import ProgressBar from '~/components/progress-bar'; + +class Example extends React.Component { + render() { + return ( +
+ +
+ ); + } +} +Example.displayName = 'ProgressBarDefault'; + +export default Example; // export is replaced with `ReactDOM.render(, mountNode);` at runtime diff --git a/components/progress-bar/__examples__/descriptive.jsx b/components/progress-bar/__examples__/descriptive.jsx new file mode 100644 index 0000000000..31b0c7a885 --- /dev/null +++ b/components/progress-bar/__examples__/descriptive.jsx @@ -0,0 +1,19 @@ +import React from 'react'; +import ProgressBar from '~/components/progress-bar'; + +class Example extends React.Component { + render() { + return ( +
+ +
+ ); + } +} +Example.displayName = 'ProgressBarDescriptive'; + +export default Example; // export is replaced with `ReactDOM.render(, mountNode);` at runtime diff --git a/components/progress-bar/__examples__/examples.jsx b/components/progress-bar/__examples__/examples.jsx new file mode 100644 index 0000000000..db45cd25c5 --- /dev/null +++ b/components/progress-bar/__examples__/examples.jsx @@ -0,0 +1,30 @@ +import React from 'react'; +import ProgressBar from '../../../components/progress-bar'; + +export const PROGRESS_0 = () => ; +export const PROGRESS_25 = () => ; +export const PROGRESS_HALF = () => ( + +); +export const PROGRESS_75 = () => ; +export const COMPLETE_100 = () => ( + +); +export const COMPLETE_WITH_DESCRIPTION = () => ( + +); +export const ROUNDED_BAR = () => ( + +); +export const X_SMALL_BAR = () => ( + +); +export const SMALL_BAR = () => ( + +); +export const MEDIUM_BAR = () => ( + +); +export const LARGE_BAR = () => ( + +); diff --git a/components/progress-bar/__examples__/radius.jsx b/components/progress-bar/__examples__/radius.jsx new file mode 100644 index 0000000000..3fbc2b818a --- /dev/null +++ b/components/progress-bar/__examples__/radius.jsx @@ -0,0 +1,16 @@ +import React from 'react'; +import ProgressBar from '~/components/progress-bar'; + +class Example extends React.Component { + render() { + return ( +
+ Radius: circular + +
+ ); + } +} +Example.displayName = 'ProgressBarRadius'; + +export default Example; // export is replaced with `ReactDOM.render(, mountNode);` at runtime diff --git a/components/progress-bar/__examples__/thickness.jsx b/components/progress-bar/__examples__/thickness.jsx new file mode 100644 index 0000000000..ac1a209e36 --- /dev/null +++ b/components/progress-bar/__examples__/thickness.jsx @@ -0,0 +1,25 @@ +import React from 'react'; +import ProgressBar from '~/components/progress-bar'; + +class Example extends React.Component { + render() { + return ( +
+ Thickness: x-small + +
+ Thickness: small + +
+ Thickness: medium + +
+ Thickness: large + +
+ ); + } +} +Example.displayName = 'ProgressBarThickness'; + +export default Example; // export is replaced with `ReactDOM.render(, mountNode);` at runtime diff --git a/components/progress-bar/docs.json b/components/progress-bar/docs.json new file mode 100644 index 0000000000..371362f7dc --- /dev/null +++ b/components/progress-bar/docs.json @@ -0,0 +1,7 @@ +{ + "component": "progress-bar", + "status": "prod", + "display-name": "Progress Bars", + "SLDS-component-path": "/components/progress-bar", + "url-slug": "progress-bars" +} diff --git a/components/progress-bar/index.jsx b/components/progress-bar/index.jsx new file mode 100644 index 0000000000..f02e1d1ff9 --- /dev/null +++ b/components/progress-bar/index.jsx @@ -0,0 +1,141 @@ +/* Copyright (c) 2015-present, salesforce.com, inc. All rights reserved */ +/* Licensed under BSD 3-Clause - see LICENSE.txt or git.io/sfdc-license */ + +// Implements the [Progress Bar design pattern](https://lightningdesignsystem.com/components/progress-ring/) in React. +// Based on SLDS v2.4.5 +import React from 'react'; +import PropTypes from 'prop-types'; +import classNames from 'classnames'; +import assign from 'lodash.assign'; + +// ### shortid +// [npmjs.com/package/shortid](https://www.npmjs.com/package/shortid) +// shortid is a short, non-sequential, url-friendly, unique id generator +import shortid from 'shortid'; +import { PROGRESS_BAR } from '../../utilities/constants'; + +const propTypes = { + /** + * HTML id for component. + */ + id: PropTypes.string, + /** + * CSS classes to be added to tag with `.slds-progress-bar`. Uses `classNames` [API](https://github.com/JedWatson/classnames). + */ + className: PropTypes.oneOfType([ + PropTypes.array, + PropTypes.object, + PropTypes.string, + ]), + /** + * Label for the progress bar + */ + labels: PropTypes.shape({ + label: PropTypes.oneOfType([PropTypes.string, PropTypes.node]), + complete: PropTypes.oneOfType([PropTypes.string, PropTypes.node]), + }), + /** + * Set radius of progress bar + */ + radius: PropTypes.oneOf(['circular']), + /** + * Set fill of progress bar + */ + color: PropTypes.oneOf(['success']), + /** + * Set progress bar thickness + */ + thickness: PropTypes.oneOf(['x-small', 'small', 'medium', 'large']), + /** + * Percentage of progress completion, ranging [0, 100]. + */ + value: PropTypes.number.isRequired, +}; + +const defaultProps = { + labels: { + complete: 'Complete', + }, +}; + +/** + * A progress bar component communicates to the user the progress of a particular process + */ +class ProgressBar extends React.Component { + componentWillMount() { + this.generatedId = shortid.generate(); + } + + /** + * ID as a string + * @returns {string} id + */ + getId() { + return this.props.id || this.generatedId; + } + + /** + * Enables Descriptive Progress Bar if label is provided + * @returns {string} description + */ + getDescription({ labels }) { + if (this.props.labels.label) { + return ( +
+ {labels.label} + +
+ ); + } + return ''; + } + + render() { + const labels = assign({}, defaultProps.labels, this.props.labels); + + return ( +
+ {this.getDescription({ labels })} +
+ + + Progress: {`${this.props.value}%`} + + +
+
+ ); + } +} + +ProgressBar.displayName = PROGRESS_BAR; +ProgressBar.propTypes = propTypes; +ProgressBar.defaultProps = defaultProps; + +export default ProgressBar; diff --git a/components/site-stories.js b/components/site-stories.js index 672a78b215..997e35d975 100644 --- a/components/site-stories.js +++ b/components/site-stories.js @@ -41,6 +41,7 @@ const documentationSiteLiveExamples = { pill: require('@salesforce/design-system-react/components/pill/__docs__/site-stories.js'), 'pill-container': require('@salesforce/design-system-react/components/pill-container/__docs__/site-stories.js'), popover: require('@salesforce/design-system-react/components/popover/__docs__/site-stories.js'), + 'progress-bar': require('@salesforce/design-system-react/components/progress-bar/__docs__/site-stories.js'), 'progress-indicator': require('@salesforce/design-system-react/components/progress-indicator/__docs__/site-stories.js'), 'progress-ring': require('@salesforce/design-system-react/components/progress-ring/__docs__/site-stories.js'), 'radio-button-group': require('@salesforce/design-system-react/components/radio-button-group/__docs__/site-stories.js'), diff --git a/components/story-based-tests.js b/components/story-based-tests.js index 4f846fc052..4376edec51 100644 --- a/components/story-based-tests.js +++ b/components/story-based-tests.js @@ -42,6 +42,7 @@ export PageHeader from '../components/page-header/__docs__/storybook-stories'; export PillContainer from '../components/pill-container/__docs__/storybook-stories'; export Popover from '../components/popover/__docs__/storybook-stories'; export ProgressIndicator from '../components/progress-indicator/__docs__/storybook-stories'; +export ProgressBar from '../components/progress-bar/__docs__/storybook-stories'; export Spinner from '../components/spinner/__docs__/storybook-stories'; // export ProgressRing from '../components/progress-ring/__docs__/storybook-stories'; // export RadioGroup from '../components/radio-group/__docs__/storybook-stories'; diff --git a/components/storybook-stories.js b/components/storybook-stories.js index 5804a4e527..eef432c9f3 100644 --- a/components/storybook-stories.js +++ b/components/storybook-stories.js @@ -48,6 +48,7 @@ export PillContainer from '../components/pill-container/__docs__/storybook-stori export Popover from '../components/popover/__docs__/storybook-stories'; export ProgressIndicator from '../components/progress-indicator/__docs__/storybook-stories'; export ProgressRing from '../components/progress-ring/__docs__/storybook-stories'; +export ProgressBar from '../components/progress-bar/__docs__/storybook-stories'; export Picklist from '../components/menu-picklist/__docs__/storybook-stories'; export RadioGroup from '../components/radio-group/__docs__/storybook-stories'; export Radio from '../components/radio/__docs__/storybook-stories'; diff --git a/package.json b/package.json index 3b5dcb6b92..50bb52cabe 100644 --- a/package.json +++ b/package.json @@ -590,6 +590,13 @@ "url-slug": "progress-indicators" }, { + "component": "progress-bar", + "status": "prod", + "display-name": "Progress Bars", + "SLDS-component-path": "/components/progress-bar", + "url-slug": "progress-bars" + }, + { "component": "progress-ring", "status": "prod", "display-name": "Progress Rings", diff --git a/tests/__image_snapshots__/story-based-tests-snapshot-test-js-image-snapshots-image-storyshots-slds-progress-bar-color-1-snap.png b/tests/__image_snapshots__/story-based-tests-snapshot-test-js-image-snapshots-image-storyshots-slds-progress-bar-color-1-snap.png new file mode 100644 index 0000000000..66de2f7153 Binary files /dev/null and b/tests/__image_snapshots__/story-based-tests-snapshot-test-js-image-snapshots-image-storyshots-slds-progress-bar-color-1-snap.png differ diff --git a/tests/__image_snapshots__/story-based-tests-snapshot-test-js-image-snapshots-image-storyshots-slds-progress-bar-default-1-snap.png b/tests/__image_snapshots__/story-based-tests-snapshot-test-js-image-snapshots-image-storyshots-slds-progress-bar-default-1-snap.png new file mode 100644 index 0000000000..b6174b87f1 Binary files /dev/null and b/tests/__image_snapshots__/story-based-tests-snapshot-test-js-image-snapshots-image-storyshots-slds-progress-bar-default-1-snap.png differ diff --git a/tests/__image_snapshots__/story-based-tests-snapshot-test-js-image-snapshots-image-storyshots-slds-progress-bar-descriptive-1-snap.png b/tests/__image_snapshots__/story-based-tests-snapshot-test-js-image-snapshots-image-storyshots-slds-progress-bar-descriptive-1-snap.png new file mode 100644 index 0000000000..077118b797 Binary files /dev/null and b/tests/__image_snapshots__/story-based-tests-snapshot-test-js-image-snapshots-image-storyshots-slds-progress-bar-descriptive-1-snap.png differ diff --git a/tests/__image_snapshots__/story-based-tests-snapshot-test-js-image-snapshots-image-storyshots-slds-progress-bar-radius-1-snap.png b/tests/__image_snapshots__/story-based-tests-snapshot-test-js-image-snapshots-image-storyshots-slds-progress-bar-radius-1-snap.png new file mode 100644 index 0000000000..28f48e396b Binary files /dev/null and b/tests/__image_snapshots__/story-based-tests-snapshot-test-js-image-snapshots-image-storyshots-slds-progress-bar-radius-1-snap.png differ diff --git a/tests/__image_snapshots__/story-based-tests-snapshot-test-js-image-snapshots-image-storyshots-slds-progress-bar-thickness-1-snap.png b/tests/__image_snapshots__/story-based-tests-snapshot-test-js-image-snapshots-image-storyshots-slds-progress-bar-thickness-1-snap.png new file mode 100644 index 0000000000..c7c66d54f3 Binary files /dev/null and b/tests/__image_snapshots__/story-based-tests-snapshot-test-js-image-snapshots-image-storyshots-slds-progress-bar-thickness-1-snap.png differ diff --git a/utilities/constants.js b/utilities/constants.js index 4df4dc18c2..a3b9e99e1b 100644 --- a/utilities/constants.js +++ b/utilities/constants.js @@ -98,6 +98,7 @@ export const PROGRESS_INDICATOR_STEP = 'SLDSProgressIndicatorStep'; export const PROGRESS_INDICATOR_STEP_VERTICAL = 'SLDSProgressIndicatorStepVertical'; export const PROGRESS_RING = 'SLDSProgressRing'; +export const PROGRESS_BAR = 'SLDSProgressBar'; export const SLIDER = 'SLDSSlider'; export const SPINNER = 'SLDSSpinner'; export const SPLIT_VIEW = 'SLDSSplitView';