* Add Muriel Styled Spinner

* Handle PR feedback: Fix ordering of example components, fix tabbing/spacing in stepper example file, and fix base muriel colors for the stepper and profile wizard.
This commit is contained in:
Justin Shreve 2019-05-23 08:42:58 -04:00 committed by GitHub
parent 0e1db89f67
commit c921593cfd
11 changed files with 206 additions and 84 deletions

View File

@ -25,6 +25,28 @@
} }
} }
.woocommerce-stepper .woocommerce-stepper__step {
.woocommerce-stepper__step-label {
color: $muriel-gray-800;
}
&.is-active,
&.is-complete {
.woocommerce-stepper__step-icon {
background: $muriel-gray-900;
color: $muriel-white;
}
.woocommerce-stepper__step-label {
color: $muriel-gray-900;
}
}
.woocommerce-spinner__circle {
stroke: $muriel-gray-900;
}
}
.woocommerce-profile-wizard__header { .woocommerce-profile-wizard__header {
height: 56px; height: 56px;
border-bottom: 1px solid $muriel-gray-50; border-bottom: 1px solid $muriel-gray-50;
@ -111,6 +133,7 @@
.woocommerce-profile-wizard__plugins-actions { .woocommerce-profile-wizard__plugins-actions {
text-align: left; text-align: left;
margin-left: 64px; margin-left: 64px;
min-height: 28px;
button { button {
display: initial; display: initial;

View File

@ -21,6 +21,7 @@
{ "component": "SearchListControl" }, { "component": "SearchListControl" },
{ "component": "Section" }, { "component": "Section" },
{ "component": "SegmentedSelection" }, { "component": "SegmentedSelection" },
{ "component": "Spinner" },
{ "component": "SplitButton" }, { "component": "SplitButton" },
{ "component": "Stepper" }, { "component": "Stepper" },
{ "component": "Summary", "render": "MySummaryList" }, { "component": "Summary", "render": "MySummaryList" },

View File

@ -7,6 +7,7 @@
- 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. - Add new component `<Stepper />` for showing a list of steps and progress.
- Add new `<Spinner />` component.
- Card component: updated default Muriel design. - Card component: updated default Muriel design.
- Card component: new `description` prop. - Card component: new `description` prop.
- Card component: new `isInactive` prop. - Card component: new `isInactive` prop.

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 Spinner } from './spinner';
export { default as Stepper } from './stepper'; 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';

View File

@ -0,0 +1,9 @@
```jsx
import { MySpinner } from '@woocommerce/components';
const MySpinner = () => (
<div>
<Spinner />
</div>
);
```

View File

@ -0,0 +1,39 @@
/** @format */
/**
* External dependencies
*/
import { Component } from '@wordpress/element';
import PropTypes from 'prop-types';
import classnames from 'classnames';
/**
* Spinner - An indeterminate circular progress indicator.
*/
class Spinner extends Component {
render() {
const { className } = this.props;
const classes = classnames( 'woocommerce-spinner', className );
return (
<svg className={ classes } viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<circle
className="woocommerce-spinner__circle"
fill="none"
strokeWidth="5"
strokeLinecap="round"
cx="50"
cy="50"
r="30"
/>
</svg>
);
}
}
Spinner.propTypes = {
/**
* Additional class name to style the component.
*/
className: PropTypes.string,
};
export default Spinner;

View File

@ -0,0 +1,38 @@
@keyframes rotate {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(270deg);
}
}
@keyframes growAndShrink {
0%,
100% {
stroke-dashoffset: 200;
}
50% {
stroke-dashoffset: 50;
transform: rotate(135deg);
}
100% {
transform: rotate(450deg);
}
}
.woocommerce-spinner {
animation: rotate 2s linear infinite;
width: 40px;
min-width: 40px;
height: 40px;
max-height: 40px;
}
.woocommerce-spinner__circle {
stroke-dasharray: 200;
stroke-dashoffset: 0;
transform-origin: center;
animation: growAndShrink 2s ease-in-out infinite;
stroke: $muriel-gray-900;
}

View File

@ -2,73 +2,82 @@
import { Stepper } from '@woocommerce/components'; import { Stepper } from '@woocommerce/components';
const MyStepper = withState( { const MyStepper = withState( {
currentStep: 'first', currentStep: 'first',
isComplete: false, isComplete: false,
} )( ( { currentStep, isComplete, setState } ) => { isPending: false,
const steps = [ } )( ( { currentStep, isComplete, isPending, setState } ) => {
{ const steps = [
label: 'First', {
key: 'first', label: 'First',
}, key: 'first',
{ },
label: 'Second', {
key: 'second', label: 'Second',
}, key: 'second',
{ },
label: 'Third', {
key: 'third', label: 'Third',
}, key: 'third',
{ },
label: 'Fourth', {
key: 'fourth', label: 'Fourth',
}, key: 'fourth',
]; },
const currentIndex = steps.findIndex( s => currentStep === s.key ); ];
if ( isComplete ) { const currentIndex = steps.findIndex( s => currentStep === s.key );
steps.forEach( s => s.isComplete = true );
}
return ( if ( isComplete ) {
<div> steps.forEach( s => s.isComplete = true );
{ 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 return (
steps={ steps } <div>
currentStep={ currentStep } { 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>
<button
onClick={ () => setState( { isPending: ! isPending } ) }
>
Toggle Spinner
</button>
</div>
) }
<Stepper
steps={ steps }
currentStep={ currentStep }
isPending={ isPending }
/>
<Stepper
isPending={ isPending }
direction="vertical"
steps={ steps }
currentStep={ currentStep }
/> />
</div>
<Stepper
direction="vertical"
steps={ steps }
currentStep={ currentStep }
/>
</div>
); );
} ); } );
``` ```

View File

@ -5,11 +5,11 @@
import classnames from 'classnames'; import classnames from 'classnames';
import { Component, Fragment } from '@wordpress/element'; import { Component, Fragment } from '@wordpress/element';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { Spinner } from '@wordpress/components';
/** /**
* Internal dependencies * Internal dependencies
*/ */
import Spinner from '../spinner';
import CheckIcon from './check-icon'; import CheckIcon from './check-icon';
/** /**
@ -32,8 +32,6 @@ class Stepper extends Component {
'is-complete': 'undefined' !== typeof isComplete ? isComplete : currentIndex > i, 'is-complete': 'undefined' !== typeof isComplete ? isComplete : currentIndex > i,
} ); } );
// @todo Update Spinner Styles
// https://material.io/design/components/progress-indicators.html
const icon = currentStep === key && isPending ? <Spinner /> : ( const icon = currentStep === key && isPending ? <Spinner /> : (
<div className="woocommerce-stepper__step-icon"> <div className="woocommerce-stepper__step-icon">
<span className="woocommerce-stepper__step-number">{ i + 1 }</span> <span className="woocommerce-stepper__step-number">{ i + 1 }</span>
@ -47,7 +45,7 @@ class Stepper extends Component {
className={ stepClassName } className={ stepClassName }
> >
{ icon } { icon }
<span className="woocommerce-stepper_step-label"> <span className="woocommerce-stepper__step-label">
{ label } { label }
</span> </span>
</div> </div>

View File

@ -1,5 +1,5 @@
.woocommerce-stepper { .woocommerce-stepper {
background: #fff; background: $muriel-white;
box-shadow: $muriel-box-shadow-1dp; box-shadow: $muriel-box-shadow-1dp;
display: flex; display: flex;
justify-content: space-around; justify-content: space-around;
@ -15,26 +15,33 @@
padding: $gap-small; padding: $gap-small;
font-weight: 400; font-weight: 400;
color: $muriel-gray-900; color: $muriel-gray-900;
height: 48px;
svg { svg {
display: none; display: none;
} }
&:not(.is-vertical).woocommerce-stepper_step-label { .woocommerce-spinner {
margin: 0 4px 0 4px; display: block;
margin-left: -$gap-smaller;
margin-right: $gap-smallest;
}
.woocommerce-spinner__circle {
stroke: $muriel-hot-blue-500;
} }
&.is-active, &.is-active,
&.is-complete { &.is-complete {
.woocommerce-stepper__step-icon, .woocommerce-stepper__step-icon {
.components-spinner { background: $muriel-hot-blue-500;
background: $muriel-hot-orange-700; color: $muriel-white;
} }
} }
&.is-active { &.is-active {
font-weight: 600; font-weight: 600;
.woocommerce-stepper_step-label { .woocommerce-stepper__step-label {
margin: 0; margin: 0;
} }
} }
@ -49,8 +56,7 @@
} }
} }
.woocommerce-stepper__step-icon, .woocommerce-stepper__step-icon {
.components-spinner {
display: inline-flex; display: inline-flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
@ -58,15 +64,11 @@
height: 24px; height: 24px;
min-width: 24px; min-width: 24px;
margin-right: $gap-small; margin-right: $gap-small;
background: $muriel-gray-300; background: $muriel-gray-50;
color: #fff; color: $muriel-gray-600;
border-radius: 50%; border-radius: 50%;
} }
.components-spinner {
margin-left: 0;
}
.woocommerce-stepper__step-divider { .woocommerce-stepper__step-divider {
flex-grow: 1; flex-grow: 1;
border-bottom: 1px solid $muriel-gray-50; border-bottom: 1px solid $muriel-gray-50;
@ -77,7 +79,7 @@
} }
@include breakpoint( '<782px' ) { @include breakpoint( '<782px' ) {
.woocommerce-stepper_step-label { .woocommerce-stepper__step-label {
display: none; display: none;
padding-top: 24px; padding-top: 24px;
} }
@ -97,7 +99,7 @@
margin-left: 24px; margin-left: 24px;
} }
.woocommerce-stepper_step-label { .woocommerce-stepper__step-label {
display: initial; display: initial;
} }

View File

@ -27,6 +27,7 @@
@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 'stepper/style.scss';
@import 'spinner/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';