Skip to content

Commit

Permalink
feat(react-iconography): add size options to iconography
Browse files Browse the repository at this point in the history
[Finishes #96041146]
  • Loading branch information
Geoff Pleiss and Matt Royal authored and Geoff Pleiss and Matt Royal committed Jun 3, 2015
1 parent f34fd1d commit 5e14a23
Show file tree
Hide file tree
Showing 6 changed files with 148 additions and 12 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
36 changes: 31 additions & 5 deletions spec/pivotal-ui-react/iconography/iconography_spec.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,42 @@
require('../spec_helper');

describe('iconography', function() {
beforeEach(function() {
var Icon = require('../../../src/pivotal-ui-react/iconography/iconography').Icon;
React.render(<Icon name="plus"/>, 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(<Icon name='plus'/>, 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(<Icon name='plus' size={size}/>, 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(<Icon name='plus' size={size}/>, 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(<Icon name='plus' className='a-class-name' size='h6'/>, root);
expect('.fa.fa-plus.a-class-name.fa-h6').toExist();
});
});
});
});
24 changes: 24 additions & 0 deletions spec/pivotal-ui-react/support/matchers.js
Original file line number Diff line number Diff line change
@@ -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};
}
};
}
};
45 changes: 42 additions & 3 deletions src/pivotal-ui-react/iconography/iconography.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,60 @@
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 (<ReactFaIcon className={`${className} fa-${size}`.trim()} {...props} />);
}
}

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 <Icon name="plus"/>;
* return <Icon name="plus" size="h5"/>;
* }
* });
* ```
*
* @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')
};
Icon: Icon
};
5 changes: 3 additions & 2 deletions src/pivotal-ui-react/iconography/package.json
Original file line number Diff line number Diff line change
@@ -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"
}
}
49 changes: 47 additions & 2 deletions src/pivotal-ui/components/iconography/iconography.scss
Original file line number Diff line number Diff line change
Expand Up @@ -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
---
Expand All @@ -122,3 +122,48 @@ To spin the icon, add `spin` to the Icon.
<UI.Icon spin name="angellist" />
```
*/

/*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
<UI.Icon name="plus" size="title" />
<UI.Icon name="plus" size="h1" />
<UI.Icon name="plus" size="h2" />
<UI.Icon name="plus" size="h3" />
<UI.Icon name="plus" size="h4" />
<UI.Icon name="plus" size="h5" />
<UI.Icon name="plus" size="h6" />
<UI.Icon name="plus" size="sm" />
<UI.Icon name="plus" size="xs" />
```
You can also pass in any FontAwesome size modifier as well.
```react_example_table
<UI.Icon name="plus" size="lg" />
<UI.Icon name="plus" size="2x" />
<UI.Icon name="plus" size="3x" />
<UI.Icon name="plus" size="4x" />
<UI.Icon name="plus" size="5x" />
```
*/

0 comments on commit 5e14a23

Please sign in to comment.