* Add Stepper component

* Add Muriel colors as variables

* Add changelog entry for Stepper component
This commit is contained in:
Joshua T Flowers 2019-05-17 16:01:40 +08:00 committed by GitHub
parent 5e07474d16
commit 8f528ee824
9 changed files with 254 additions and 0 deletions

View File

@ -22,6 +22,7 @@
{ "component": "Section" }, { "component": "Section" },
{ "component": "SegmentedSelection" }, { "component": "SegmentedSelection" },
{ "component": "SplitButton" }, { "component": "SplitButton" },
{ "component": "Stepper" },
{ "component": "Summary", "render": "MySummaryList" }, { "component": "Summary", "render": "MySummaryList" },
{ "component": "Table" }, { "component": "Table" },
{ "component": "Tag" }, { "component": "Tag" },

View File

@ -57,3 +57,7 @@ $core-orange: #ca4a1f;
$button: #f0f2f4; $button: #f0f2f4;
$button-border: darken($button, 20%); $button-border: darken($button, 20%);
// Muriel
$muriel-gray-dark-300: #969ca1;
$muriel-active: #bb4f10;

View File

@ -6,6 +6,7 @@
- Tweaks to SummaryListPlaceholder height in order to better match SummaryNumber. - Tweaks to SummaryListPlaceholder height in order to better match SummaryNumber.
- EllipsisMenu component (breaking change): Remove `children` prop in favor of a render prop `renderContent` so that function arguments `isOpen`, `onToggle`, and `onClose` can be passed down. - EllipsisMenu component (breaking change): Remove `children` prop in favor of a render prop `renderContent` so that function arguments `isOpen`, `onToggle`, and `onClose` can be passed down.
- Chart has a new prop named `yBelow1Format` which overrides the `yFormat` for values between -1 and 1 (not included). - Chart has a new prop named `yBelow1Format` which overrides the `yFormat` for values between -1 and 1 (not included).
- Add new component `<Stepper />` for showing a list of steps and progress.
# 2.0.0 # 2.0.0
- Chart legend component now uses withInstanceId HOC so the ids used in several HTML elements are unique. - Chart legend component now uses withInstanceId HOC so the ids used in several HTML elements are unique.

View File

@ -40,6 +40,7 @@ export { default as SearchListItem } from './search-list-control/item';
export { default as SectionHeader } from './section-header'; export { default as SectionHeader } from './section-header';
export { default as SegmentedSelection } from './segmented-selection'; export { default as SegmentedSelection } from './segmented-selection';
export { default as SplitButton } from './split-button'; export { default as SplitButton } from './split-button';
export { default as Stepper } from './stepper';
export { default as SummaryList } from './summary'; export { default as SummaryList } from './summary';
export { default as SummaryListPlaceholder } from './summary/placeholder'; export { default as SummaryListPlaceholder } from './summary/placeholder';
export { default as SummaryNumber } from './summary/number'; export { default as SummaryNumber } from './summary/number';

View File

@ -0,0 +1,22 @@
/** @format */
export default () => (
<svg
role="img"
aria-hidden="true"
focusable="false"
width="18"
height="18"
viewBox="0 0 18 18"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<mask id="mask0" mask-type="alpha" maskUnits="userSpaceOnUse" x="2" y="3" width="14" height="12">
<path d="M6.59631 11.9062L3.46881 8.77875L2.40381 9.83625L6.59631 14.0287L15.5963
5.02875L14.5388 3.97125L6.59631 11.9062Z" fill="white" />
</mask>
<g mask="url(#mask0)">
<rect width="18" height="18" fill="white" />
</g>
</svg>
);

View File

@ -0,0 +1,68 @@
```jsx
import { Stepper } from '@woocommerce/components';
const MyStepper = withState( {
currentStep: 'first',
isComplete: false,
} )( ( { currentStep, isComplete, setState } ) => {
const steps = [
{
label: 'First',
key: 'first',
},
{
label: 'Second',
key: 'second',
},
{
label: 'Third',
key: 'third',
},
{
label: 'Fourth',
key: 'fourth',
},
];
const currentIndex = steps.findIndex( s => currentStep === s.key );
if ( isComplete ) {
steps.forEach( s => s.isComplete = true );
}
return (
<div>
{ isComplete ? (
<button onClick={ () => setState( { currentStep: 'first', isComplete: false } ) } >
Reset
</button>
) : (
<div>
<button
onClick={ () => setState( { currentStep: steps[ currentIndex - 1 ]['key'] } ) }
disabled={ currentIndex < 1 }
>
Previous step
</button>
<button
onClick={ () => setState( { currentStep: steps[ currentIndex + 1 ]['key'] } ) }
disabled={ currentIndex >= steps.length - 1 }
>
Next step
</button>
<button
onClick={ () => setState( { isComplete: true } ) }
disabled={ currentIndex !== steps.length - 1 }
>
Complete
</button>
</div>
) }
<Stepper
steps={ steps }
currentStep={ currentStep }
/>
</div>
);
} );
```

View File

@ -0,0 +1,84 @@
/** @format */
/**
* External dependencies
*/
import classnames from 'classnames';
import { Component, Fragment } from '@wordpress/element';
import PropTypes from 'prop-types';
/**
* Internal dependencies
*/
import CheckIcon from './check-icon';
/**
* A stepper component to indicate progress in a set number of steps.
*/
class Stepper extends Component {
render() {
const { className, currentStep, steps } = this.props;
const currentIndex = steps.findIndex( s => currentStep === s.key );
const stepperClassName = classnames( 'woocommerce-stepper', className );
return (
<div className={ stepperClassName }>
{ steps.map( ( step, i ) => {
const { key, label, isComplete } = step;
const stepClassName = classnames( 'woocommerce-stepper__step', {
'is-active': key === currentStep,
'is-complete': 'undefined' !== typeof isComplete ? isComplete : currentIndex > i,
} );
return (
<Fragment key={ key } >
<div
className={ stepClassName }
>
<div className="woocommerce-stepper__step-icon">
<span className="woocommerce-stepper__step-number">{ i + 1 }</span>
<CheckIcon />
</div>
<span className="woocommerce-stepper_step-label">
{ label }
</span>
</div>
<div className="woocommerce-stepper__step-divider" />
</Fragment>
);
} ) }
</div>
);
}
}
Stepper.propTypes = {
/**
* Additional class name to style the component.
*/
className: PropTypes.string,
/**
* The current step's key.
*/
currentStep: PropTypes.string.isRequired,
/**
* An array of steps used.
*/
steps: PropTypes.arrayOf(
PropTypes.shape( {
/**
* Key used to identify step.
*/
key: PropTypes.string.isRequired,
/**
* Label displayed in stepper.
*/
label: PropTypes.string.isRequired,
/**
* Optionally mark a step complete regardless of step index.
*/
isComplete: PropTypes.bool,
} )
).isRequired,
};
export default Stepper;

View File

@ -0,0 +1,72 @@
.woocommerce-stepper {
background: #fff;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2),
0 2px 2px rgba(0, 0, 0, 0.12),
0 0 2px rgba(0, 0, 0, 0.14);
display: flex;
justify-content: space-around;
align-items: center;
margin-bottom: $gap-large;
padding-left: $gap;
padding-right: $gap;
font-size: 16px;
.woocommerce-stepper__step {
display: inline-flex;
align-items: center;
padding: $gap-small;
font-weight: 600;
svg {
display: none;
}
&.is-active,
&.is-complete {
color: $muriel-active;
.woocommerce-stepper__step-icon {
background: $muriel-active;
}
}
&.is-complete {
.woocommerce-stepper__step-number {
display: none;
}
svg {
display: inline;
}
}
}
.woocommerce-stepper__step-icon {
display: inline-flex;
align-items: center;
justify-content: center;
width: 24px;
height: 24px;
margin-right: $gap-small;
background: $muriel-gray-dark-300;
color: #fff;
border-radius: 50%;
}
.woocommerce-stepper__step-divider {
flex-grow: 1;
border-bottom: 1px solid $muriel-gray-dark-300;
&:last-child {
display: none;
}
}
@include breakpoint( '<782px' ) {
.woocommerce-stepper_step-label {
display: none;
}
.woocommerce-stepper__step-icon {
margin-right: 0;
}
}
}

View File

@ -26,6 +26,7 @@
@import 'section-header/style.scss'; @import 'section-header/style.scss';
@import 'segmented-selection/style.scss'; @import 'segmented-selection/style.scss';
@import 'split-button/style.scss'; @import 'split-button/style.scss';
@import 'stepper/style.scss';
@import 'summary/style.scss'; @import 'summary/style.scss';
@import 'table/style.scss'; @import 'table/style.scss';
@import 'tag/style.scss'; @import 'tag/style.scss';