Skip to content

Commit

Permalink
Merge pull request #6043 from stunaz/next
Browse files Browse the repository at this point in the history
[Badge] Port Badge Component
  • Loading branch information
oliviertassinari authored Feb 7, 2017
2 parents 2226613 + 8fcaca0 commit 9a50136
Show file tree
Hide file tree
Showing 7 changed files with 285 additions and 0 deletions.
18 changes: 18 additions & 0 deletions docs/api/Badge/Badge.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
Badge
======



Props
-----

| Name | Type | Default | Description |
|:-----|:-----|:--------|:------------|
| accent | bool | false | If true, the badge will use the accent badge colors. |
| badgeClassName | string | | The CSS class name of the badge element. |
| <span style="color: #31a148">badgeContent *</span> | node | | This is the content rendered within the badge. |
| <span style="color: #31a148">children *</span> | node | | The node that the badge will be applied to. |
| className | string | | The CSS class name of the root element. |
| primary | bool | false | If true, the badge will use the primary badge colors. |

Any other properties supplied will be spread to the root element.
39 changes: 39 additions & 0 deletions docs/site/src/demos/badges/SimpleBadge.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// @flow weak

import React from 'react';
import { createStyleSheet } from 'jss-theme-reactor';
import Badge from 'material-ui/Badge';
import customPropTypes from 'material-ui/utils/customPropTypes';
import Icon from 'material-ui/Icon';

const styleSheet = createStyleSheet('SimpleBadge', () => ({
badge: {
margin: '0 20px',
},
}));

export default function SimpleBadge(props, context) {
const classes = context.styleManager.render(styleSheet);
return (
<div className={classes.row}>
<Badge
badgeContent={4}
className={classes.badge}
primary
>
<Icon>mail</Icon>
</Badge>
<Badge
accent
badgeContent={10}
className={classes.badge}
>
<Icon>folder</Icon>
</Badge>
</div>
);
}

SimpleBadge.contextTypes = {
styleManager: customPropTypes.muiRequired,
};
10 changes: 10 additions & 0 deletions docs/site/src/demos/badges/badges.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Badge

Badge generates a small badge to the top-right of its child(ren).

## Simple examples

Two examples of badges containing text, using primary and secondary colors. The badge is applied to its children - an icon for the first example, and an Icon Button with tooltip for the second.

{{demo='demos/badges/SimpleBadge.js'}}

113 changes: 113 additions & 0 deletions src/Badge/Badge.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
// @flow weak

import React, { PropTypes } from 'react';
import classNames from 'classnames';
import { createStyleSheet } from 'jss-theme-reactor';
import customPropTypes from '../utils/customPropTypes';

const radius = 12;
const radius2x = 2 * radius;

export const styleSheet = createStyleSheet('Badge', (theme) => {
const { typography, palette } = theme;

return {
root: {
position: 'relative',
display: 'inline-block',
},
badge: {
display: 'flex',
flexDirection: 'row',
flexWrap: 'wrap',
justifyContent: 'center',
alignContent: 'center',
alignItems: 'center',
position: 'absolute',
top: `-${radius}px`,
right: `-${radius}px`,
fontWeight: typography.fontWeight,
fontSize: radius,
width: radius2x,
height: radius2x,
borderRadius: '50%',
backgroundColor: palette.color,
color: palette.textColor,
},
primary: {
backgroundColor: palette.primary[500],
color: palette.getContrastText(palette.primary[500]),
},
accent: {
backgroundColor: palette.accent.A200,
color: palette.getContrastText(palette.accent.A200),
},
};
});

export default function Badge(props, context) {
const {
badgeClassName: badgeClassNameProp,
badgeContent,
className: classNameProp,
children,
primary,
accent,
...other
} = props;

const classes = context.styleManager.render(styleSheet);
const className = classNames({
[classes.root]: true,
}, classNameProp);
const badgeClassName = classNames({
[classes.badge]: true,
[classes.primary]: primary,
[classes.accent]: accent,
}, badgeClassNameProp);

return (
<div className={className} {...other}>
{children}
<span className={badgeClassName}>
{badgeContent}
</span>
</div>
);
}

Badge.propTypes = {
/**
* If true, the badge will use the accent badge colors.
*/
accent: PropTypes.bool,
/**
* The css class name of the badge element.
*/
badgeClassName: PropTypes.string,
/**
* This is the content rendered within the badge.
*/
badgeContent: PropTypes.node.isRequired,
/**
* The badge will be added relativelty to this node.
*/
children: PropTypes.node.isRequired,
/**
* The css class name of the root element.
*/
className: PropTypes.string,
/**
* If true, the badge will use the primary badge colors.
*/
primary: PropTypes.bool,
};

Badge.defaultProps = {
primary: false,
accent: false,
};

Badge.contextTypes = {
styleManager: customPropTypes.muiRequired,
};
89 changes: 89 additions & 0 deletions src/Badge/Badge.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
// @flow weak
/* eslint-env mocha */
import React from 'react';
import { createShallowWithContext } from 'test/utils';
import { assert } from 'chai';
import Badge, { styleSheet } from './Badge';

describe('<Badge />', () => {
let shallow;
let classes;

before(() => {
shallow = createShallowWithContext();
classes = shallow.context.styleManager.render(styleSheet);
});

const testChildren = <div className="unique">Hello World</div>;

it('renders children and badgeContent', () => {
const wrapper = shallow(
<Badge badgeContent={10}>{testChildren}</Badge>,
);

assert.strictEqual(wrapper.contains(testChildren), true, 'should contain the children');
assert.ok(wrapper.find('span').length, 'should contain the badgeContent');
});

it('renders children and overwrite badge class', () => {
const badgeClassName = 'testBadgeClassName';

const wrapper = shallow(
<Badge badgeContent={10} badgeClassName={badgeClassName}>{testChildren}</Badge>,
);

assert.strictEqual(wrapper.contains(testChildren), true, 'should contain the children');
assert.strictEqual(wrapper.find('span').hasClass('testBadgeClassName'), true,
'should contain the badgeClassName');
});

it('renders children by default', () => {
const wrapper = shallow(
<Badge badgeContent={10}>{testChildren}</Badge>,
);

assert.strictEqual(wrapper.contains(testChildren), true, 'should contain the children');
});

it('renders children and className', () => {
const wrapper = shallow(
<Badge badgeContent={10} className="testClassName">{testChildren}</Badge>,
);

assert.strictEqual(wrapper.contains(testChildren), true, 'should contain the children');
assert.strictEqual(wrapper.is('.testClassName'), true, 'should contain the className');
});

it('renders children and have primary styles', () => {
const wrapper = shallow(
<Badge badgeContent={10} primary>{testChildren}</Badge>,
);

assert.strictEqual(wrapper.contains(testChildren), true, 'should contain the children');
assert.strictEqual(wrapper.find('span').hasClass(classes.primary), true,
'should have primary class');
});

it('renders children and have accent styles', () => {
const wrapper = shallow(
<Badge badgeContent={10} accent>{testChildren}</Badge>,
);

assert.strictEqual(wrapper.contains(testChildren), true, 'should contain the children');
assert.strictEqual(wrapper.find('span').hasClass(classes.accent), true,
'should have accent class');
});

it('renders children and overwrite root styles', () => {
const style = {
backgroundColor: 'red',
};
const wrapper = shallow(
<Badge badgeContent={10} style={style}>{testChildren}</Badge>,
);

assert.strictEqual(wrapper.contains(testChildren), true, 'should contain the children');
assert.strictEqual(wrapper.node.props.style.backgroundColor, style.backgroundColor,
'should overwrite badge backgroundColor');
});
});
3 changes: 3 additions & 0 deletions src/Badge/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
/* eslint-disable flowtype/require-valid-file-annotation */

export default from './Badge';
13 changes: 13 additions & 0 deletions test/regressions/site/src/tests/Badge/Badge.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// @flow weak

import React from 'react';
import Badge from 'material-ui/Badge';
import Icon from 'material-ui/Icon';

export default function SimpleBadge() {
return (
<Badge badgeContent={1} primary>
<Icon>mail</Icon>
</Badge>
);
}

0 comments on commit 9a50136

Please sign in to comment.