Skip to content

Commit

Permalink
Merge pull request #301 from appfolio/updateSteps
Browse files Browse the repository at this point in the history
Update Steps
  • Loading branch information
gthomas-appfolio authored Sep 19, 2017
2 parents fc2c9fe + d9e8561 commit 5cb5c39
Show file tree
Hide file tree
Showing 3 changed files with 124 additions and 63 deletions.
118 changes: 77 additions & 41 deletions src/components/Steps.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,52 +4,88 @@ import classNames from 'classnames';
import Icon from './Icon.js';
import styles from './Steps.scss';

const Steps = ({ complete, step, steps }) => {
const className = `${styles.steps} ${complete ? styles.complete : ''}`;
const Steps = ({ collapse, complete, step, steps }) => {
const className = classNames({
[styles.complete]: complete,
[styles.steps]: true,
'm-0': true
});
const activeStep = steps[step];
const activeStepClasses = classNames({
'text-gray-dark': !complete,
'text-success': complete,
'hidden-sm-up': collapse !== true,
'text-center': true
});

return (
<ol className={className}>
{steps.map((name, index) => {
const stepComplete = !complete && index < step;
const stepActive = !complete && index === step;

const liClasses = classNames({
[styles.step]: true,
[styles.complete]: stepComplete,
[styles.active]: stepActive,
});

const bubbleClasses = classNames({
[styles.bubble]: true,
'text-success': complete,
'bg-primary': stepActive,
'text-primary': stepComplete,
'text-white': stepActive,
});

const textClasses = classNames({
[styles.text]: true,
'text-primary': stepComplete,
'text-muted': !complete && index > step,
'text-success': complete,
});

return (
<li key={index} className={liClasses}>
<div className={bubbleClasses}>
{complete || stepComplete ? <Icon name="check" /> : index + 1}
</div>
<div className={textClasses}>{name}</div>
</li>
);
})}
</ol>
<div className="mb-3">
<ol className={className}>
{steps.map((name, index) => {
const stepComplete = !complete && index < step;
const stepActive = !complete && index === step;

const liClasses = classNames({
[styles.step]: true,
[styles.complete]: stepComplete,
[styles.active]: stepActive,
'text-success': complete,
'text-primary': !complete && (stepComplete || stepActive),
'text-muted': !(stepComplete || stepActive || complete)
});

const bubbleClasses = classNames({
[styles.bubble]: true,
'text-success': complete,
'bg-primary': stepActive,
'text-primary': stepActive || stepComplete,
'text-muted': !stepComplete && !stepActive
});

const iconClasses = classNames({
'text-primary': stepComplete,
'text-white': stepActive,
'text-gray-dark': !(complete || stepComplete || stepActive),
'text-success': complete
});

const textClasses = classNames({
'hidden-xs-down': collapse !== false,
'text-primary': stepComplete,
'text-muted': !complete && index > step,
'text-success': complete,
'text-gray-dark': stepActive,
});

return (
<li key={index} className={liClasses}>
<div className={bubbleClasses}>
<span className={iconClasses}>{complete || stepComplete ? <Icon name="check" /> : index + 1}</span>
</div>
{collapse !== true ? <label className={textClasses}>{name}</label> : null}
</li>
);
})}
</ol>
{collapse !== false ?
<div className={activeStepClasses}>
<label>{activeStep}</label>
</div> : null}
</div>
);
};

Steps.propTypes = {
step: PropTypes.number,
steps: PropTypes.array.isRequired,
complete: PropTypes.bool
collapse: PropTypes.bool,
complete: PropTypes.bool,
step: PropTypes.number.isRequired,
steps: PropTypes.array.isRequired
};

Steps.defaultProps = {
complete: false,
step: 0,
steps: []
};

export default Steps;
30 changes: 12 additions & 18 deletions src/components/Steps.scss
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
// TODO these colors need to instead come from Bootstrap classes like muted/info/success/etc for theming:
$line: 1px;
$done: #0275d8; // Saffron color-primary
$active: #0275d8;
$todo: #818a91; // Saffron color-muted
$complete: #21971d; // Saffron color-success
$todo: #818a91; // Saffron color-muted, needs to be text-muted

.steps {
align-items: flex-start;
Expand Down Expand Up @@ -31,16 +28,16 @@ $complete: #21971d; // Saffron color-success
background-image: linear-gradient(to right, transparent 50%, $todo 50%, $todo 100%);
}
&.complete {
background-image: linear-gradient(to right, transparent 50%, $done 50%, $done 100%);
background-image: linear-gradient(to right, transparent 50%, currentColor 50%, currentColor 100%);
}
}
&:last-child {
background-image: linear-gradient(to right, $todo 50%, transparent 50%, transparent 100%);
&.active {
background-image: linear-gradient(to right, $done 50%, transparent 50%, transparent 100%);
background-image: linear-gradient(to right, currentColor 50%, transparent 50%, transparent 100%);
}
&.complete {
background-image: linear-gradient(to right, $done 50%, transparent 50%, transparent 100%);
background-image: linear-gradient(to right, currentColor 50%, transparent 50%, transparent 100%);
}
}

Expand All @@ -59,34 +56,31 @@ $complete: #21971d; // Saffron color-success
}

&.active {
background-image: linear-gradient(to right, $done 50%, $todo 50%, $todo 100%);
background-image: linear-gradient(to right, currentColor 50%, $todo 50%, $todo 100%);
.bubble {
border: $line solid $active;
border: $line solid currentColor;
}
}

&.complete {
background-image: linear-gradient(to right, $done, $done);
background-image: linear-gradient(to right, currentColor, currentColor);
.bubble {
border: $line solid $done;
border: $line solid currentColor;
}
}
}

&.complete {
.step {
background-image: linear-gradient(to right, $complete, $complete);
background-image: linear-gradient(to right, currentColor, currentColor);
.bubble {
border: $line solid $complete;
}
.text {
opacity: .5;
border: $line solid currentColor;
}
&:first-child {
background-image: linear-gradient(to right, transparent 50%, $complete 50%, $complete 100%);
background-image: linear-gradient(to right, transparent 50%, currentColor 50%, currentColor 100%);
}
&:last-child {
background-image: linear-gradient(to right, $complete 50%, transparent 50%, transparent 100%);
background-image: linear-gradient(to right, currentColor 50%, transparent 50%, transparent 100%);
}
}
}
Expand Down
39 changes: 35 additions & 4 deletions test/components/Steps.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,45 @@ import { mount } from 'enzyme';

import { Steps } from '../../src';

const steps = ['Alpha', 'Bravo', 'Charlie', 'Delta'];

describe('<Steps />', () => {
it('should render correctly', () => {
const steps = ['Alpha', 'Bravo', 'Charlie', 'Delta'];
const component = mount(<Steps steps={steps} />);
assert(component);
});

it('should show correct number of steps');
it('should activated the current step');
it('should show complete correctly');
it('should show correct number of steps', () => {
const component = mount(<Steps steps={steps} />);
assert.equal(component.find('li').length, steps.length);
});

it('should activate the current step', () => {
const component = mount(<Steps steps={steps} step={2} />);
assert.equal(component.find('label.text-gray-dark').text(), steps[2]);
});

it('should show complete correctly', () => {
const component = mount(<Steps steps={steps} step={2} complete />);
assert.equal(component.find('li.text-success').length, steps.length);
});

describe('collapse', () => {
it('should default to showing responsive step labels', () => {
const component = mount(<Steps steps={steps} />);
assert.equal(component.find('label').length, steps.length + 1);
assert.equal(component.find('label.hidden-xs-down').length, steps.length);
assert.equal(component.find('.hidden-sm-up label').length, 1);
});

it('should only show non-responsive step labels when collapse=false', () => {
const component = mount(<Steps steps={steps} collapse={false} />);
assert.equal(component.find('label').length, steps.length);
});

it('should only show active step label when collapse=true', () => {
const component = mount(<Steps steps={steps} collapse />);
assert.equal(component.find('label').length, 1);
});
});
});

0 comments on commit 5cb5c39

Please sign in to comment.