Skip to content

Commit

Permalink
Add support for colored Badge component (#220)
Browse files Browse the repository at this point in the history
* Add PRIMARY and NEUTRAL color constants

* Add Badge color variations

* Add Badge coloring tests

* Update Badge component

* Remove null onClick from defaultProps

* Update spec description

* Update Badge snapshots
  • Loading branch information
felixjung authored and fernandofleury committed Jul 9, 2018
1 parent c72f2d9 commit 180727b
Show file tree
Hide file tree
Showing 6 changed files with 232 additions and 38 deletions.
83 changes: 68 additions & 15 deletions src/components/Badge/Badge.js
Original file line number Diff line number Diff line change
@@ -1,27 +1,71 @@
import PropTypes from 'prop-types';
import styled, { css } from 'react-emotion';
import { size } from 'polished';
import { values } from 'lodash/fp';

import { subHeadingKilo } from '../../styles/style-helpers';
import { colorNames } from '../../styles/constants';

const baseStyles = ({ theme }) => css`
const COLOR_MAP = {
[colorNames.SUCCESS]: {
default: 'g500',
hover: 'g700',
active: 'g900'
},
[colorNames.WARNING]: {
default: 'y500',
hover: 'y700',
active: 'y900'
},
[colorNames.DANGER]: {
default: 'r500',
hover: 'r700',
active: 'r900'
},
[colorNames.PRIMARY]: {
default: 'b500',
hover: 'b700',
active: 'b900'
},
[colorNames.NEUTRAL]: {
default: 'n500',
hover: 'n700',
active: 'n900'
}
};

const colorStyles = ({ theme, color, onClick }) => {
const currentColor = COLOR_MAP[color];

if (!currentColor) {
return null;
}

return css`
label: badge--${color};
background-color: ${theme.colors[currentColor.default]};
${onClick &&
`
&:hover {
background-color: ${theme.colors[currentColor.hover]};
}
&:active {
background-color: ${theme.colors[currentColor.active]};
}
`};
`;
};

const baseStyles = ({ theme, onClick }) => css`
label: badge;
background-color: ${theme.colors.r500};
border-radius: 100px;
color: ${theme.colors.white};
cursor: default;
cursor: ${onClick ? 'pointer' : 'default'};
padding: 0 ${theme.spacings.byte};
${subHeadingKilo({ theme })};
text-transform: uppercase;
user-select: none;
&:hover {
background-color: ${theme.colors.r700};
}
&:active {
background-color: ${theme.colors.r900};
}
`;

const circleStyles = ({ circle }) =>
Expand All @@ -37,7 +81,9 @@ const circleStyles = ({ circle }) =>
* A badge for displaying update notifications etc.
*/
const Badge = styled('div')`
${baseStyles} ${circleStyles};
${baseStyles};
${colorStyles};
${circleStyles};
`;

Badge.propTypes = {
Expand All @@ -48,12 +94,19 @@ Badge.propTypes = {
/**
* Ensures text is centered and the badge looks like a circle.
*/
circle: PropTypes.bool
circle: PropTypes.bool,
color: PropTypes.oneOf(values(colorNames))
};

Badge.NEUTRAL = colorNames.NEUTRAL;
Badge.PRIMARY = colorNames.PRIMARY;
Badge.SUCCESS = colorNames.SUCCESS;
Badge.WARNING = colorNames.WARNING;
Badge.DANGER = colorNames.DANGER;

Badge.defaultProps = {
onClick: () => {},
circle: false
circle: false,
color: Badge.NEUTRAL
};

/**
Expand Down
27 changes: 27 additions & 0 deletions src/components/Badge/Badge.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,33 @@ describe('Badge', () => {
expect(actual).toMatchSnapshot();
});

describe('rendering color variations', () => {
it('should render with success colors', () => {
const actual = create(<Badge color={Badge.SUCCESS} />);
expect(actual).toMatchSnapshot();
});

it('should render with warning colors', () => {
const actual = create(<Badge color={Badge.WARNING} />);
expect(actual).toMatchSnapshot();
});

it('should render with danger colors', () => {
const actual = create(<Badge color={Badge.DANGER} />);
expect(actual).toMatchSnapshot();
});

it('should render with primary colors', () => {
const actual = create(<Badge color={Badge.PRIMARY} />);
expect(actual).toMatchSnapshot();
});
});

it('should have hover/active styles only when the onClick handler is provided', () => {
const actual = create(<Badge onClick={() => {}} />);
expect(actual).toMatchSnapshot();
});

it('should have the correct circle styles', () => {
const actual = create(<Badge circle />);
expect(actual).toMatchSnapshot();
Expand Down
11 changes: 10 additions & 1 deletion src/components/Badge/Badge.story.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,23 @@
import React, { Fragment } from 'react';
import { storiesOf } from '@storybook/react';
import { withInfo } from '@storybook/addon-info';
import { select } from '@storybook/addon-knobs/react';
import { values } from 'lodash/fp';

import { GROUPS } from '../../../.storybook/hierarchySeparators';
import { colorNames } from '../../styles/constants';

import withTests from '../../util/withTests';
import Badge from './Badge';

storiesOf(`${GROUPS.COMPONENTS}|Badge`, module)
.addDecorator(withTests('Badge'))
.add('Default Badge', withInfo()(() => <Badge>Update</Badge>))
.add(
'Default Badge',
withInfo()(() => (
<Badge color={select('Color', values(colorNames))}>Update</Badge>
))
)
.add(
'Circular Badge',
withInfo()(() => (
Expand Down
143 changes: 123 additions & 20 deletions src/components/Badge/__snapshots__/Badge.spec.js.snap
Original file line number Diff line number Diff line change
@@ -1,8 +1,126 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`Badge should have the correct circle styles 1`] = `
exports[`Badge rendering color variations should render with danger colors 1`] = `
.circuit-0 {
border-radius: 100px;
color: #FFFFFF;
cursor: default;
padding: 0 8px;
font-size: 12px;
line-height: 20px;
text-transform: uppercase;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
background-color: #FF7559;
}
<div
className="circuit-0 circuit-1"
color="danger"
/>
`;

exports[`Badge rendering color variations should render with primary colors 1`] = `
.circuit-0 {
border-radius: 100px;
color: #FFFFFF;
cursor: default;
padding: 0 8px;
font-size: 12px;
line-height: 20px;
text-transform: uppercase;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
background-color: #3388FF;
}
<div
className="circuit-0 circuit-1"
color="primary"
/>
`;

exports[`Badge rendering color variations should render with success colors 1`] = `
.circuit-0 {
border-radius: 100px;
color: #FFFFFF;
cursor: default;
padding: 0 8px;
font-size: 12px;
line-height: 20px;
text-transform: uppercase;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
background-color: #62DE76;
}
<div
className="circuit-0 circuit-1"
color="success"
/>
`;

exports[`Badge rendering color variations should render with warning colors 1`] = `
.circuit-0 {
border-radius: 100px;
color: #FFFFFF;
cursor: default;
padding: 0 8px;
font-size: 12px;
line-height: 20px;
text-transform: uppercase;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
background-color: #FFC859;
}
<div
className="circuit-0 circuit-1"
color="warning"
/>
`;

exports[`Badge should have hover/active styles only when the onClick handler is provided 1`] = `
.circuit-0 {
border-radius: 100px;
color: #FFFFFF;
cursor: pointer;
padding: 0 8px;
font-size: 12px;
line-height: 20px;
text-transform: uppercase;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
background-color: #9DA7B1;
}
.circuit-0:hover {
background-color: #5C656F;
}
.circuit-0:active {
background-color: #212933;
}
<div
className="circuit-0 circuit-1"
color="neutral"
onClick={[Function]}
/>
`;

exports[`Badge should have the correct circle styles 1`] = `
.circuit-0 {
border-radius: 100px;
color: #FFFFFF;
cursor: default;
Expand All @@ -14,6 +132,7 @@ exports[`Badge should have the correct circle styles 1`] = `
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
background-color: #9DA7B1;
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
Expand All @@ -30,23 +149,14 @@ exports[`Badge should have the correct circle styles 1`] = `
width: 24px;
}
.circuit-0:hover {
background-color: #D55A41;
}
.circuit-0:active {
background-color: #A73D28;
}
<div
className="circuit-0 circuit-1"
onClick={[Function]}
color="neutral"
/>
`;

exports[`Badge should render with default styles 1`] = `
.circuit-0 {
background-color: #FF7559;
border-radius: 100px;
color: #FFFFFF;
cursor: default;
Expand All @@ -58,18 +168,11 @@ exports[`Badge should render with default styles 1`] = `
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.circuit-0:hover {
background-color: #D55A41;
}
.circuit-0:active {
background-color: #A73D28;
background-color: #9DA7B1;
}
<div
className="circuit-0 circuit-1"
onClick={[Function]}
color="neutral"
/>
`;
4 changes: 2 additions & 2 deletions src/styles/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import {
BIT, BYTE, KILO, MEGA, GIGA, TERA, PETA, EXA, ZETTA,
SINGLE, DOUBLE, TRIPLE,
SUCCESS, DANGER, WARNING
SUCCESS, DANGER, WARNING, PRIMARY, NEUTRAL
} from '../util/constants';

/**
Expand All @@ -21,7 +21,7 @@ export const shadows = { SINGLE, DOUBLE, TRIPLE };
* Colors?
*/

export const colorNames = { SUCCESS, DANGER, WARNING };
export const colorNames = { SUCCESS, DANGER, WARNING, PRIMARY, NEUTRAL };

/**
* Directions
Expand Down
2 changes: 2 additions & 0 deletions src/util/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,5 @@ export const TRIPLE = 'triple';
export const SUCCESS = 'success';
export const DANGER = 'danger';
export const WARNING = 'warning';
export const NEUTRAL = 'neutral';
export const PRIMARY = 'primary';

0 comments on commit 180727b

Please sign in to comment.