diff --git a/package.json b/package.json index 03cdfd85e..4153e550d 100644 --- a/package.json +++ b/package.json @@ -70,6 +70,7 @@ "node-libs-browser": "^0.5.2", "node-sass": "^2.1.1", "npm": "^2.7.5", + "object-assign": "^2.0.0", "pui-react-animation": "0.0.6", "q": "^1.0.1", "react": "0.13.3", diff --git a/spec/pivotal-ui-react/iconography/iconography_spec.js b/spec/pivotal-ui-react/iconography/iconography_spec.js index 699868201..b914101e5 100644 --- a/spec/pivotal-ui-react/iconography/iconography_spec.js +++ b/spec/pivotal-ui-react/iconography/iconography_spec.js @@ -1,16 +1,42 @@ require('../spec_helper'); -describe('iconography', function() { - beforeEach(function() { - var Icon = require('../../../src/pivotal-ui-react/iconography/iconography').Icon; - React.render(, root); - }); +var Icon = require('../../../src/pivotal-ui-react/iconography/iconography').Icon; +var {toBeValid} = require('../support/matchers'); +describe('iconography', function() { afterEach(function() { React.unmountComponentAtNode(root); }); it('works', function() { + React.render(, root); expect('.fa.fa-plus').toExist(); }); + + describe('when a size is given', function() { + beforeEach(function() { + jasmine.addMatchers({toBeValid}); + }); + + it('does not fail prop-validation', function() { + for (var size of ['title', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'sm', 'xs', 'lg', '2x', '3x', '4x', '5x']) { + expect(, root).toBeValid(); + } + }); + + it('adds the size class to the icon', function() { + for (var size of ['title', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'sm', 'xs', 'lg', '2x', '3x', '4x', '5x']) { + React.render(, root); + expect('.fa.fa-plus').toHaveClass(`fa-${size}`); + React.unmountComponentAtNode(root); + } + }); + + describe('when a className and a size are given', function() { + it('adds the size class to the icon and includes the given className also', function() { + React.render(, root); + expect('.fa.fa-plus.a-class-name.fa-h6').toExist(); + }); + }); + }); }); diff --git a/spec/pivotal-ui-react/support/matchers.js b/spec/pivotal-ui-react/support/matchers.js new file mode 100644 index 000000000..d9aa44e41 --- /dev/null +++ b/spec/pivotal-ui-react/support/matchers.js @@ -0,0 +1,24 @@ +module.exports = { + toBeValid: function() { + return { + compare: function(element) { + const Klass = element.type; + + const errorMessages = Object.keys(Klass.propTypes).reduce(function(memo, prop) { + const error = Klass.propTypes[prop](element.props, prop); + if (error) { + memo.push(error.message); + } + return memo; + }, []); + + var pass = !errorMessages.length; + var message = pass ? + `Expected element not to be a valid ${Klass.name}` : + `Expected element to be a valid ${Klass.name}. Validation errors:\n ${errorMessages.join('\n ')}`; + + return {pass, message}; + } + }; + } +}; diff --git a/src/pivotal-ui-react/iconography/iconography.js b/src/pivotal-ui-react/iconography/iconography.js index 566d52ae5..7942f798a 100644 --- a/src/pivotal-ui-react/iconography/iconography.js +++ b/src/pivotal-ui-react/iconography/iconography.js @@ -1,15 +1,54 @@ +const React = require('react'); +const {PropTypes} = React; +const ReactFaIcon = require('react-fa/dist/Icon'); +const objectAssign = require('object-assign'); + +class Icon extends React.Component { + render() { + const {size, className, ...props} = this.props; + + return (); + } +} + +function satisfiesOneOf(...propTypes) { + return function(props, propName, componentName) { + var error; + var errorMessages = []; + for (var propType of propTypes) { + error = propType(props, propName, componentName); + if (!error) { + return null; + } else { + errorMessages.push(error.message); + } + } + + return new Error(`Failed to satisfy any of the possible requirements:\n ${errorMessages.join('\n ')}`); + }; +} + +Icon.propTypes = objectAssign({}, ReactFaIcon.propTypes, { + size: satisfiesOneOf( + ReactFaIcon.propTypes.size, + PropTypes.oneOf([ 'title', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'sm', 'xs' ]) + ) +}); + module.exports = { /** * @component Icon * @description Inserts a Font Awesome icon * * @property name {String} The name of the icon (without the fa- prefix) + * @property size {String} Can either be a PUI typography size (title, h1, + * h2, h3, h4, h5, h6, sm, xs) or a FA size (lg, 2x, 3x, 4x, 5x). * * @example ```js * var Icon = require('pui-react-iconography').Icon; * var MyComponent = React.createClass({ * render() { - * return ; + * return ; * } * }); * ``` @@ -17,5 +56,5 @@ module.exports = { * @see [Pivotal UI React](http://styleguide.pivotal.io/react_beta.html#icon_react) * @see [Pivotal UI CSS](http://styleguide.pivotal.io/elements.html#iconography) */ - Icon: require('react-fa/dist/Icon') -}; \ No newline at end of file + Icon: Icon +}; diff --git a/src/pivotal-ui-react/iconography/package.json b/src/pivotal-ui-react/iconography/package.json index dc761ceb6..7069232c3 100644 --- a/src/pivotal-ui-react/iconography/package.json +++ b/src/pivotal-ui-react/iconography/package.json @@ -1,9 +1,10 @@ { - "version": "0.1.0", + "version": "0.2.0", "description": "A React component for rendering Font Awesome icons", "homepage": "http://styleguide.pivotal.io/react_beta.html#icon_react", "dependencies": { "react-fa": "^3.0.0", - "pui-css-iconography": "^0" + "pui-css-iconography": "^0", + "object-assign": "^2.0.0" } } diff --git a/src/pivotal-ui/components/iconography/iconography.scss b/src/pivotal-ui/components/iconography/iconography.scss index f0dfef6a9..5129eda3d 100644 --- a/src/pivotal-ui/components/iconography/iconography.scss +++ b/src/pivotal-ui/components/iconography/iconography.scss @@ -106,8 +106,8 @@ Don't use the typography size modifier classes (e.g. .title, .h1, .type-sm) /*doc --- -title: Icons -name: icon_react +title: Iconography +name: iconography_react categories: - React Beta --- @@ -122,3 +122,48 @@ To spin the icon, add `spin` to the Icon. ``` */ + +/*doc +--- +title: React Iconography Sizing +name: iconography_sizing_react +parent: iconography_react +--- + +Pass in any PUI typography size modifier in the size attribute. +These are useful if you want your icon to match the size of a text element. + +```react_example_table + + + + + + + + + + + + + + + + + +``` + +You can also pass in any FontAwesome size modifier as well. + +```react_example_table + + + + + + + + + +``` +*/