Skip to content

Commit

Permalink
refactor(ffe-icons-react): Improve API
Browse files Browse the repository at this point in the history
BREAKING CHANGE: Improve the API of ffe-icons-react.

This commit changes the API of the ffe-icons-react package to take
advantage of dead code eliminination and tree shaking in
Webpack >= 2.

Previously, you imported one and one icon from the corresponding
JSX file. Now all icons are available as named exports from the
root level of `ffe-icons-react`.

If you're using webpack@>=2.0.0,  please make the following changes
to migrate:

```diff
- import ChevronIkon from 'ffe-icons-react/chevron-ikon';
- import FamilieIkon from 'ffe-icons-react/familie-ikon';
+ import { ChevronIkon, FamilieIkon } from 'ffe-icons-react';
```

If you're not using a build tool that enables dead code elimination
and tree shaking, please make the following changes to migrate:

```diff
- import ChevronIkon from 'ffe-icons-react/chevron-ikon';
- import FamilieIkon from 'ffe-icons-react/familie-ikon';
+ import ChevronIkon from 'ffe-icons-react/lib/chevron-ikon';
+ import FamilieIkon from 'ffe-icons-react/lib/familie-ikon';
```

This API change allows for cleaner usage and better documentation.
  • Loading branch information
Kristofer Selbekk committed Dec 27, 2017
1 parent 7258fcc commit e9b88a4
Show file tree
Hide file tree
Showing 13 changed files with 66 additions and 117 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
"babel-preset-env": "^1.6.1",
"babel-preset-react": "^6.24.1",
"babel-preset-stage-3": "^6.24.1",
"case": "^1.5.4",
"css-loader": "^0.28.7",
"husky": "^0.14.3",
"lerna": "^2.5.1",
Expand Down
2 changes: 1 addition & 1 deletion packages/ffe-buttons-react/examples/buttons.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from 'react';
import { render } from 'react-dom';
import FaksPrinterSolidIkon from 'ffe-icons-react/faks-printer-solid-ikon';
import { FaksPrinterSolidIkon } from 'ffe-icons-react';
import './buttons.less';
import {
ActionButton,
Expand Down
4 changes: 2 additions & 2 deletions packages/ffe-buttons-react/src/ShortcutButton.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import React from 'react';
import ChevronIcon from 'ffe-icons-react/chevron-ikon';
import { ChevronIkon } from 'ffe-icons-react';
import Button from './Button';

const ShortcutButton = props => (
<Button
buttonType="shortcut"
rightIcon={<ChevronIcon className="ffe-shortcut-button__icon-chevron" />}
rightIcon={<ChevronIkon className="ffe-shortcut-button__icon-chevron" />}
{...props}
/>
);
Expand Down
10 changes: 7 additions & 3 deletions packages/ffe-icons-react/.gitignore
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
.idea/
# Dependencies
node_modules/

# Editors
.idea/

# Built files
iconlist.json
jsx/
tmp/
/*-ikon.js
/ffe-icons-react.js
lib/
3 changes: 0 additions & 3 deletions packages/ffe-icons-react/.npmignore
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
buildCI.sh
src/build-iconlist.js
src/build-jsx-components.js
clean.js
src/example.jsx
index.html
iconlist.json
svg.sprite.config.json
webpack.config.js
src/icons.js.mustache
39 changes: 0 additions & 39 deletions packages/ffe-icons-react/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,46 +10,7 @@ npm install --save ffe-icons-react

## Usage

Import the main module and use iconName as a prop.

```javascript
import React from 'react';
import Icon from 'ffe-icons-react';

<Icon className="icon" iconName="chevron-ikon"/>
```
Note that doing this will inline every single icon we have
available in your final bundle so you might want to avoid
doing this for production code

Alternatively import each icon as a sub module.

```javascript
import React from 'react';
import ChevronIcon from 'ffe-icons-react/chevron-ikon';

<ChevronIcon className="icon"/>
```
Doing this will ensure that only the icons you actually
use are sent to the client.

### Available props

```
className: PropTypes.string
desc: PropTypes.string
focusable: PropTypes.bool
onClick: PropTypes.func
style: PropTypes.object
tabIndex: PropTypes.number
title: PropTypes.string
```

* Use css and `className` to change size and color, or use `style` and react inline styles.
* Use `desc` to create a `<desc></desc>` element inside the icon. Default is `''`.
* Use `focusable` to make svg focusable on old IE. Default is false.
* Use `tabIndex` to set tabIndex of the icon. Default is undefined.
* Use `title` to create a `<title></title>` element inside the icon. Default is `''`.

## Utvikling og bidrag

Expand Down
15 changes: 13 additions & 2 deletions packages/ffe-icons-react/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,21 @@
<title>ffe-icons-react</title>
</head>
<body>
<style type="text/css">
<style>
.example-container {
display: flex;
flex-wrap: wrap;
}
.icon-container {
font-family: sans-serif;
flex: 1;
padding: 1em;
text-align: center;
}
.icon {
width: 100px;
height: auto;
padding-bottom: 1em;
width: 100px;
}
</style>
<div id="app"></div>
Expand Down
18 changes: 7 additions & 11 deletions packages/ffe-icons-react/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,16 @@
"name": "ffe-icons-react",
"version": "3.0.0",
"description": "React-komponenter for ffe-icons",
"main": "ffe-icons-react.js",
"main": "lib/index.js",
"scripts": {
"build": "npm run ffe:icons && npm run build:iconlist && npm run build:jsx-components && npm run build:babel",
"build:babel": "babel jsx -d .",
"build:iconlist": "babel-node ./src/build-iconlist.js",
"build": "npm run ffe:icons && npm run build:jsx-components && npm run build:babel",
"build:babel": "babel jsx -d lib",
"build:jsx-components": "babel-node ./src/build-jsx-components.js",
"clean": "rimraf tmp jsx lib",
"lint": "eslint src",
"lint:jsx": "eslint ./jsx/*.jsx",
"pretest": "eslint src/ jsx/*.jsx",
"test": "nsp check",
"clean": "rimraf tmp jsx *-ikon.js ffe-icons-react.js",
"test": "nsp check && npm run lint",
"ffe:icons": "ffe-icons --opts=packages/ffe-icons-react/svg.sprite.config.json",
"start": "npm run build && npm run build:iconlist && webpack-dev-server",
"server": "webpack-dev-server"
"start": "npm run build && webpack-dev-server"
},
"repository": {
"type": "git",
Expand Down Expand Up @@ -46,6 +42,6 @@
"webpack-dev-server": "^2.7.1"
},
"files": [
"*.js"
"lib"
]
}
9 changes: 0 additions & 9 deletions packages/ffe-icons-react/src/build-iconlist.js

This file was deleted.

40 changes: 18 additions & 22 deletions packages/ffe-icons-react/src/build-jsx-components.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import icons from './../tmp/icons';
import caseUtil from 'case';
import fs from 'fs';
import mkdirp from 'mkdirp';
import icons from '../tmp/icons';

mkdirp.sync('./jsx');

Expand All @@ -18,21 +19,21 @@ const camelCaseSVGProps = svgString =>
.replace(/stroke-miterlimit/g, 'strokeMiterlimit');

/**
* Creates a new React component and a corresponding .jsx file for each icon. .
* Creates a new React component and a corresponding .jsx file for each icon
* */
const createStandaloneJSX = iconName => `
import React from 'react';
import { bool, func, number, object, string } from 'prop-types';
import { bool, string } from 'prop-types';
const svg = ${camelCaseSVGProps(icons[iconName])};
const Icon = ({
desc = '',
desc,
focusable = false,
title = '',
title,
iconName,
...rest
}) =>
}) => (
<svg focusable={String(focusable)} {...rest} {...svg.props}>
{title &&
<title>{title}</title>
Expand All @@ -41,32 +42,27 @@ const Icon = ({
<desc>{desc}</desc>
}
{svg.props.children}
</svg>;
</svg>
);
Icon.propTypes = {
className: string,
desc: string,
focusable: bool,
onClick: func,
style: object,
tabIndex: number,
title: string,
iconName: string,
};
Icon.displayName = '${caseUtil.pascal(iconName)}';
export default Icon;
`;
Object.keys(icons).map((iconName) => fs.writeFileSync(`./jsx/${iconName}.jsx`, createStandaloneJSX(iconName)));
Object.keys(icons).forEach((iconName) => fs.writeFileSync(`./jsx/${iconName}.js`, createStandaloneJSX(iconName)));

/**
* Creates a list of strings on the form ['bil-ikon': require('./bil-ikon')',] from icons.
* The list is then interpolated with surrounding brackets to create a js object in the outputted file.
* */
const createAllJSX = iconsObjectString => `
const icons = {${iconsObjectString}};
export default props => icons[props.iconName] ? icons[props.iconName].default(props) : null;
`;
const iconsObjectString = Object.keys(icons)
.map(iconname => `'${iconname}': require('./${iconname}')`);
* Creates an index file that exports all icons
*/
const indexFileString = Object.keys(icons)
.map(iconName => `export { default as ${caseUtil.pascal(iconName)} } from './${iconName}';`)
.join('\n');

fs.writeFileSync('./jsx/ffe-icons-react.jsx', createAllJSX(iconsObjectString));
fs.writeFileSync('./jsx/index.js', indexFileString);
15 changes: 15 additions & 0 deletions packages/ffe-icons-react/src/example.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import React from 'react';
import ReactDOM from 'react-dom';
import * as icons from '../lib';

ReactDOM.render(
<div className="example-container">
{Object.entries(icons).map(([iconName, Icon]) => (
<div className="icon-container" key={iconName}>
<Icon className="icon" />
<p>{iconName}</p>
</div>
))}
</div>,
document.getElementById('app')
);
20 changes: 0 additions & 20 deletions packages/ffe-icons-react/src/example.jsx

This file was deleted.

7 changes: 2 additions & 5 deletions packages/ffe-icons-react/webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,9 @@ const path = require('path');
module.exports = {
devtool: 'cheap-module-source-map',
entry: [
'webpack-dev-server/client?http://localhost:8080',
'webpack-dev-server/client?http://localhost:8081',
'./src/example'
],
resolve: {
extensions: ['.js', '.jsx']
},
output: {
path: path.join(__dirname, 'tmp'),
filename: 'bundle.js',
Expand All @@ -17,7 +14,7 @@ module.exports = {
module: {
rules: [
{
test: /\.jsx?$/,
test: /\.js$/,
loader: 'babel-loader',
exclude: /node_modules/,
}
Expand Down

0 comments on commit e9b88a4

Please sign in to comment.