From 09250d63f3c933a6a5b3349cc8a67c803289f18c Mon Sep 17 00:00:00 2001 From: stunaz Date: Mon, 30 Jan 2017 23:38:51 -0500 Subject: [PATCH 1/7] [Badge] Port Badge Component --- docs/api/Badge/Badge.md | 18 ++++ docs/site/src/demos/badges/FurtherBadge.js | 37 +++++++ docs/site/src/demos/badges/SimpleBadge.js | 39 +++++++ docs/site/src/demos/badges/badges.md | 15 +++ src/Badge/Badge.js | 115 +++++++++++++++++++++ src/Badge/Badge.spec.js | 89 ++++++++++++++++ src/Badge/index.js | 3 + src/svg-icons/notification.js | 15 +++ 8 files changed, 331 insertions(+) create mode 100644 docs/api/Badge/Badge.md create mode 100644 docs/site/src/demos/badges/FurtherBadge.js create mode 100644 docs/site/src/demos/badges/SimpleBadge.js create mode 100644 docs/site/src/demos/badges/badges.md create mode 100644 src/Badge/Badge.js create mode 100644 src/Badge/Badge.spec.js create mode 100644 src/Badge/index.js create mode 100644 src/svg-icons/notification.js diff --git a/docs/api/Badge/Badge.md b/docs/api/Badge/Badge.md new file mode 100644 index 00000000000000..d14112ea955409 --- /dev/null +++ b/docs/api/Badge/Badge.md @@ -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. | +| badgeContent * | node | | This is the content rendered within the badge. | +| children | node | | The badge will be added relativelty to this node. | +| 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. diff --git a/docs/site/src/demos/badges/FurtherBadge.js b/docs/site/src/demos/badges/FurtherBadge.js new file mode 100644 index 00000000000000..b736a330423a46 --- /dev/null +++ b/docs/site/src/demos/badges/FurtherBadge.js @@ -0,0 +1,37 @@ +// @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 IconButton from 'material-ui/IconButton'; +import ImageIcon from 'material-ui/svg-icons/image'; +import FaceIcon from 'material-ui/svg-icons/face'; + +const styleSheet = createStyleSheet('FurtherBadge', () => ({ + badge: { + fontSize: 20, + right: 12, + }, +})); + +export default function FurtherBadge(props, context) { + const classes = context.styleManager.render(styleSheet); + return ( +
+ }> + + + + Company Name + +
+ ); +} + +FurtherBadge.contextTypes = { + styleManager: customPropTypes.muiRequired, +}; diff --git a/docs/site/src/demos/badges/SimpleBadge.js b/docs/site/src/demos/badges/SimpleBadge.js new file mode 100644 index 00000000000000..87273bfccce281 --- /dev/null +++ b/docs/site/src/demos/badges/SimpleBadge.js @@ -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 IconButton from 'material-ui/IconButton'; +import NotificationIcon from 'material-ui/svg-icons/notification'; + +const styleSheet = createStyleSheet('SimpleBadge', () => ({ + badge: { + top: 12, + right: 12, + }, +})); + +export default function SimpleBadge(props, context) { + const classes = context.styleManager.render(styleSheet); + return ( +
+ + + + + + + + +
+ ); +} + +SimpleBadge.contextTypes = { + styleManager: customPropTypes.muiRequired, +}; diff --git a/docs/site/src/demos/badges/badges.md b/docs/site/src/demos/badges/badges.md new file mode 100644 index 00000000000000..f224ac90d04906 --- /dev/null +++ b/docs/site/src/demos/badges/badges.md @@ -0,0 +1,15 @@ +# 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'}} + +## Further examples + +Badges containing an Icon Button and text, applied to an icon, and text. + +{{demo='demos/badges/FurtherBadge.js'}} diff --git a/src/Badge/Badge.js b/src/Badge/Badge.js new file mode 100644 index 00000000000000..e5137924d4c27e --- /dev/null +++ b/src/Badge/Badge.js @@ -0,0 +1,115 @@ +// @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 = Math.floor(2 * radius); + +export const styleSheet = createStyleSheet('Badge', (theme) => { + const { typography, palette } = theme; + + return { + root: { + position: 'relative', + display: 'inline-block', + padding: `${radius2x}px ${radius2x}px ${radius}px ${radius}px`, + }, + badge: { + display: 'flex', + flexDirection: 'row', + flexWrap: 'wrap', + justifyContent: 'center', + alignContent: 'center', + alignItems: 'center', + position: 'absolute', + top: 0, + right: 0, + 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, // eslint-disable-line no-unused-vars + accent, // eslint-disable-line no-unused-vars + ...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 ( +
+ {children} + + {badgeContent} + +
+ ); +} + +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, + /** + * 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, +}; diff --git a/src/Badge/Badge.spec.js b/src/Badge/Badge.spec.js new file mode 100644 index 00000000000000..b5dcf58262a50e --- /dev/null +++ b/src/Badge/Badge.spec.js @@ -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('', () => { + let shallow; + let classes; + + before(() => { + shallow = createShallowWithContext(); + classes = shallow.context.styleManager.render(styleSheet); + }); + + const testChildren =
Hello World
; + + it('renders children and badgeContent', () => { + const wrapper = shallow( + {testChildren}, + ); + + 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( + {testChildren}, + ); + + 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( + {testChildren}, + ); + + assert.strictEqual(wrapper.contains(testChildren), true, 'should contain the children'); + }); + + it('renders children and className', () => { + const wrapper = shallow( + {testChildren}, + ); + + 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( + {testChildren}, + ); + + 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( + {testChildren}, + ); + + 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( + {testChildren}, + ); + + assert.strictEqual(wrapper.contains(testChildren), true, 'should contain the children'); + assert.strictEqual(wrapper.node.props.style.backgroundColor, style.backgroundColor, + 'should overwrite badge backgroundColor'); + }); +}); diff --git a/src/Badge/index.js b/src/Badge/index.js new file mode 100644 index 00000000000000..40b8b2acdc3ba9 --- /dev/null +++ b/src/Badge/index.js @@ -0,0 +1,3 @@ +/* eslint-disable flowtype/require-valid-file-annotation */ + +export default from './Badge'; diff --git a/src/svg-icons/notification.js b/src/svg-icons/notification.js new file mode 100644 index 00000000000000..12c38e848e003c --- /dev/null +++ b/src/svg-icons/notification.js @@ -0,0 +1,15 @@ +/* eslint-disable */ + +import React from 'react'; +import pure from 'recompose/pure'; +import SvgIcon from '../SvgIcon'; + +let Notification = (props) => ( + + + +); +Notification = pure(Notification); +Notification.muiName = 'SvgIcon'; + +export default Notification; From 6ab0e9c96bf1981095590ebbd9fba89ad1e04415 Mon Sep 17 00:00:00 2001 From: stunaz Date: Tue, 31 Jan 2017 00:19:18 -0500 Subject: [PATCH 2/7] [Badge] Port Badge Component --- docs/site/src/demos/badges/FurtherBadge.js | 4 ++-- docs/site/src/demos/badges/SimpleBadge.js | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/site/src/demos/badges/FurtherBadge.js b/docs/site/src/demos/badges/FurtherBadge.js index b736a330423a46..bb10d1a12d578b 100644 --- a/docs/site/src/demos/badges/FurtherBadge.js +++ b/docs/site/src/demos/badges/FurtherBadge.js @@ -22,10 +22,10 @@ export default function FurtherBadge(props, context) { }> - + > Company Name diff --git a/docs/site/src/demos/badges/SimpleBadge.js b/docs/site/src/demos/badges/SimpleBadge.js index 87273bfccce281..29425d01bf0e37 100644 --- a/docs/site/src/demos/badges/SimpleBadge.js +++ b/docs/site/src/demos/badges/SimpleBadge.js @@ -18,14 +18,14 @@ export default function SimpleBadge(props, context) { const classes = context.styleManager.render(styleSheet); return (
- + - + > From df9bf25c22545ca4b2bb8eeee00d40182d0c7fb0 Mon Sep 17 00:00:00 2001 From: stunaz Date: Tue, 31 Jan 2017 00:26:40 -0500 Subject: [PATCH 3/7] [Badge] Port Badge Component --- docs/site/src/demos/badges/SimpleBadge.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/site/src/demos/badges/SimpleBadge.js b/docs/site/src/demos/badges/SimpleBadge.js index 29425d01bf0e37..841fb5bfcabc4b 100644 --- a/docs/site/src/demos/badges/SimpleBadge.js +++ b/docs/site/src/demos/badges/SimpleBadge.js @@ -22,8 +22,8 @@ export default function SimpleBadge(props, context) { From c4c17ceb62480745fcb6c332b8a09ef6907eeff8 Mon Sep 17 00:00:00 2001 From: stunaz Date: Tue, 31 Jan 2017 20:24:10 -0500 Subject: [PATCH 4/7] - lint convention - set children as required prop - remove useless lint comment --- docs/api/Badge/Badge.md | 2 +- src/Badge/Badge.js | 9 ++++----- src/Badge/Badge.spec.js | 8 ++++---- 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/docs/api/Badge/Badge.md b/docs/api/Badge/Badge.md index d14112ea955409..23d57f69e7c1d8 100644 --- a/docs/api/Badge/Badge.md +++ b/docs/api/Badge/Badge.md @@ -11,7 +11,7 @@ Props | accent | bool | false | If true, the badge will use the accent badge colors. | | badgeClassName | string | | The CSS class name of the badge element. | | badgeContent * | node | | This is the content rendered within the badge. | -| children | node | | The badge will be added relativelty to this node. | +| children * | node | | The badge will be added relativelty to this node. | | className | string | | The CSS class name of the root element. | | primary | bool | false | If true, the badge will use the primary badge colors. | diff --git a/src/Badge/Badge.js b/src/Badge/Badge.js index e5137924d4c27e..c520399fbbd8d5 100644 --- a/src/Badge/Badge.js +++ b/src/Badge/Badge.js @@ -6,7 +6,7 @@ import { createStyleSheet } from 'jss-theme-reactor'; import customPropTypes from '../utils/customPropTypes'; const radius = 12; -const radius2x = Math.floor(2 * radius); +const radius2x = 2 * radius; export const styleSheet = createStyleSheet('Badge', (theme) => { const { typography, palette } = theme; @@ -52,8 +52,8 @@ export default function Badge(props, context) { badgeContent, className: classNameProp, children, - primary, // eslint-disable-line no-unused-vars - accent, // eslint-disable-line no-unused-vars + primary, + accent, ...other } = props; @@ -67,7 +67,6 @@ export default function Badge(props, context) { [classes.accent]: accent, }, badgeClassNameProp); - return (
{children} @@ -94,7 +93,7 @@ Badge.propTypes = { /** * The badge will be added relativelty to this node. */ - children: PropTypes.node, + children: PropTypes.node.isRequired, /** * The css class name of the root element. */ diff --git a/src/Badge/Badge.spec.js b/src/Badge/Badge.spec.js index b5dcf58262a50e..8583ad96423b7c 100644 --- a/src/Badge/Badge.spec.js +++ b/src/Badge/Badge.spec.js @@ -34,7 +34,7 @@ describe('', () => { assert.strictEqual(wrapper.contains(testChildren), true, 'should contain the children'); assert.strictEqual(wrapper.find('span').hasClass('testBadgeClassName'), true, - 'should contain the badgeClassName'); + 'should contain the badgeClassName'); }); it('renders children by default', () => { @@ -61,7 +61,7 @@ describe('', () => { assert.strictEqual(wrapper.contains(testChildren), true, 'should contain the children'); assert.strictEqual(wrapper.find('span').hasClass(classes.primary), true, - 'should have primary class'); + 'should have primary class'); }); it('renders children and have accent styles', () => { @@ -71,7 +71,7 @@ describe('', () => { assert.strictEqual(wrapper.contains(testChildren), true, 'should contain the children'); assert.strictEqual(wrapper.find('span').hasClass(classes.accent), true, - 'should have accent class'); + 'should have accent class'); }); it('renders children and overwrite root styles', () => { @@ -84,6 +84,6 @@ describe('', () => { assert.strictEqual(wrapper.contains(testChildren), true, 'should contain the children'); assert.strictEqual(wrapper.node.props.style.backgroundColor, style.backgroundColor, - 'should overwrite badge backgroundColor'); + 'should overwrite badge backgroundColor'); }); }); From 11c87b6b0510b501e1e6ffa242122684a2720a64 Mon Sep 17 00:00:00 2001 From: stunaz Date: Tue, 31 Jan 2017 20:31:35 -0500 Subject: [PATCH 5/7] docs --- docs/api/Badge/Badge.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/api/Badge/Badge.md b/docs/api/Badge/Badge.md index 23d57f69e7c1d8..f0cf3808cec141 100644 --- a/docs/api/Badge/Badge.md +++ b/docs/api/Badge/Badge.md @@ -11,7 +11,7 @@ Props | accent | bool | false | If true, the badge will use the accent badge colors. | | badgeClassName | string | | The CSS class name of the badge element. | | badgeContent * | node | | This is the content rendered within the badge. | -| children * | node | | The badge will be added relativelty to this node. | +| children * | 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. | From 852cffe72a964f3783631a0ddc0b51484831363f Mon Sep 17 00:00:00 2001 From: stunaz Date: Sun, 5 Feb 2017 20:27:34 -0500 Subject: [PATCH 6/7] adjusted the examples --- docs/site/src/demos/badges/FurtherBadge.js | 37 ------------------- docs/site/src/demos/badges/SimpleBadge.js | 22 +++++------ docs/site/src/demos/badges/badges.md | 5 --- src/Badge/Badge.js | 5 +-- src/svg-icons/notification.js | 15 -------- .../regressions/site/src/tests/Badge/Badge.js | 13 +++++++ 6 files changed, 26 insertions(+), 71 deletions(-) delete mode 100644 docs/site/src/demos/badges/FurtherBadge.js delete mode 100644 src/svg-icons/notification.js create mode 100644 test/regressions/site/src/tests/Badge/Badge.js diff --git a/docs/site/src/demos/badges/FurtherBadge.js b/docs/site/src/demos/badges/FurtherBadge.js deleted file mode 100644 index bb10d1a12d578b..00000000000000 --- a/docs/site/src/demos/badges/FurtherBadge.js +++ /dev/null @@ -1,37 +0,0 @@ -// @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 IconButton from 'material-ui/IconButton'; -import ImageIcon from 'material-ui/svg-icons/image'; -import FaceIcon from 'material-ui/svg-icons/face'; - -const styleSheet = createStyleSheet('FurtherBadge', () => ({ - badge: { - fontSize: 20, - right: 12, - }, -})); - -export default function FurtherBadge(props, context) { - const classes = context.styleManager.render(styleSheet); - return ( -
- }> - - - - Company Name - -
- ); -} - -FurtherBadge.contextTypes = { - styleManager: customPropTypes.muiRequired, -}; diff --git a/docs/site/src/demos/badges/SimpleBadge.js b/docs/site/src/demos/badges/SimpleBadge.js index 841fb5bfcabc4b..6787501c07eb07 100644 --- a/docs/site/src/demos/badges/SimpleBadge.js +++ b/docs/site/src/demos/badges/SimpleBadge.js @@ -4,31 +4,31 @@ import React from 'react'; import { createStyleSheet } from 'jss-theme-reactor'; import Badge from 'material-ui/Badge'; import customPropTypes from 'material-ui/utils/customPropTypes'; -import IconButton from 'material-ui/IconButton'; -import NotificationIcon from 'material-ui/svg-icons/notification'; +import Icon from 'material-ui/Icon'; const styleSheet = createStyleSheet('SimpleBadge', () => ({ badge: { - top: 12, - right: 12, - }, + margin: '0 20px', + } })); export default function SimpleBadge(props, context) { const classes = context.styleManager.render(styleSheet); return (
- - + + mail - - - + folder
); diff --git a/docs/site/src/demos/badges/badges.md b/docs/site/src/demos/badges/badges.md index f224ac90d04906..068cbdb7ff6b02 100644 --- a/docs/site/src/demos/badges/badges.md +++ b/docs/site/src/demos/badges/badges.md @@ -8,8 +8,3 @@ Two examples of badges containing text, using primary and secondary colors. The {{demo='demos/badges/SimpleBadge.js'}} -## Further examples - -Badges containing an Icon Button and text, applied to an icon, and text. - -{{demo='demos/badges/FurtherBadge.js'}} diff --git a/src/Badge/Badge.js b/src/Badge/Badge.js index c520399fbbd8d5..b18d333269f72b 100644 --- a/src/Badge/Badge.js +++ b/src/Badge/Badge.js @@ -15,7 +15,6 @@ export const styleSheet = createStyleSheet('Badge', (theme) => { root: { position: 'relative', display: 'inline-block', - padding: `${radius2x}px ${radius2x}px ${radius}px ${radius}px`, }, badge: { display: 'flex', @@ -25,8 +24,8 @@ export const styleSheet = createStyleSheet('Badge', (theme) => { alignContent: 'center', alignItems: 'center', position: 'absolute', - top: 0, - right: 0, + top: `-${radius}px`, + right: `-${radius}px`, fontWeight: typography.fontWeight, fontSize: radius, width: radius2x, diff --git a/src/svg-icons/notification.js b/src/svg-icons/notification.js deleted file mode 100644 index 12c38e848e003c..00000000000000 --- a/src/svg-icons/notification.js +++ /dev/null @@ -1,15 +0,0 @@ -/* eslint-disable */ - -import React from 'react'; -import pure from 'recompose/pure'; -import SvgIcon from '../SvgIcon'; - -let Notification = (props) => ( - - - -); -Notification = pure(Notification); -Notification.muiName = 'SvgIcon'; - -export default Notification; diff --git a/test/regressions/site/src/tests/Badge/Badge.js b/test/regressions/site/src/tests/Badge/Badge.js new file mode 100644 index 00000000000000..d680b36a7b2518 --- /dev/null +++ b/test/regressions/site/src/tests/Badge/Badge.js @@ -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 ( + + mail + + ); +} From 8fcaca081dcf18815b474d68b3c4952f4adc83cb Mon Sep 17 00:00:00 2001 From: stunaz Date: Sun, 5 Feb 2017 20:41:35 -0500 Subject: [PATCH 7/7] Fix lint issue --- docs/site/src/demos/badges/SimpleBadge.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/site/src/demos/badges/SimpleBadge.js b/docs/site/src/demos/badges/SimpleBadge.js index 6787501c07eb07..696f9fbb91022a 100644 --- a/docs/site/src/demos/badges/SimpleBadge.js +++ b/docs/site/src/demos/badges/SimpleBadge.js @@ -9,14 +9,14 @@ 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 (
-