Merge pull request #5 from Tiqa/tech/add-storybook

Tech/add storybook
This commit is contained in:
ato 2016-11-05 11:22:57 +01:00 committed by GitHub
commit 983ca41e2a
18 changed files with 186 additions and 88 deletions

View file

@ -1,4 +1,4 @@
{
"presets": ["es2015", "stage-0", "react"],
"presets": ["es2015", "react", "stage-0"],
"plugins": ["transform-decorators-legacy", "lodash", "react-hot-loader/babel"]
}

3
.storybook/addons.js Normal file
View file

@ -0,0 +1,3 @@
import '@kadira/storybook/addons';
import '@kadira/storybook-addon-knobs/register';
import 'storybook-readme/register';

11
.storybook/config.js Normal file
View file

@ -0,0 +1,11 @@
import React from 'react';
import { configure, setAddon } from '@kadira/storybook';
import infoAddon from '@kadira/react-storybook-addon-info';
setAddon(infoAddon);
function loadStories() {
require('../stories/index.js');
}
configure(loadStories, module);

View file

@ -0,0 +1,3 @@
const webpack = require('../webpack/webpack.base.config.js');
module.exports = webpack;

View file

@ -16,7 +16,9 @@
"lint-fix": "eslint src --fix",
"test": "karma start",
"e2e-test": "./node_modules/.bin/nightwatch",
"setup-test": "node selenium-download.js"
"setup-test": "node selenium-download.js",
"storybook": "start-storybook -p 6006",
"build-storybook": "build-storybook"
},
"dependencies": {
"axios": "^0.14.0",
@ -28,14 +30,14 @@
"node-polyglot": "^2.0.0",
"node-sass": "^3.8.0",
"ramda": "^0.21.0",
"react": "^15.2.0",
"react-addons-css-transition-group": "^15.2.0",
"react-addons-shallow-compare": "^15.2.0",
"react-addons-transition-group": "^15.2.0",
"react": "^15.3.2",
"react-addons-css-transition-group": "^15.3.2",
"react-addons-shallow-compare": "^15.3.2",
"react-addons-transition-group": "^15.3.2",
"react-bootstrap": "^0.30.3",
"react-click-outside": "^2.1.0",
"react-css-modules": "^3.7.6",
"react-dom": "^15.2.0",
"react-dom": "^15.3.2",
"react-immutable-proptypes": "^2.1.0",
"react-polyglot": "^0.1.0",
"react-pure-render": "^1.0.2",
@ -45,7 +47,6 @@
"react-router-redux": "~4.0.0",
"redux": "^3.0.4",
"redux-immutable": "^3.0.6",
"redux-json-api": "^1.4.4",
"redux-saga": "^0.11.0",
"reselect": "^2.5.1",
"resolve-url-loader": "^1.6.0",
@ -54,6 +55,9 @@
"url-loader": "^0.5.7"
},
"devDependencies": {
"@kadira/react-storybook-addon-info": "^3.3.0",
"@kadira/storybook": "^2.5.2",
"@kadira/storybook-addon-knobs": "^1.4.1",
"babel-cli": "<6.3.0",
"babel-core": "<6.3.0",
"babel-eslint": "^6.0.0",
@ -107,6 +111,7 @@
"postcss-modules": "^0.4.1",
"postcss-short-position": "^1.0.0",
"promise-loader": "^1.0.0",
"raw-loader": "^0.5.1",
"react-addons-perf": "^15.2.0",
"react-hot-loader": "^3.0.0-beta.2",
"redux-devtools": "^3.1.1",
@ -115,6 +120,7 @@
"shelljs": "^0.7.0",
"sinon": "^1.17.4",
"sinon-chai": "^2.8.0",
"storybook-readme": "^1.2.0",
"style-loader": "^0.13.0",
"stylelint": "^6.6.0",
"webpack": "1.12.10",

View file

@ -0,0 +1,17 @@
PublicFigureAvatar
================
# Introduction
Let's pretend this component has a readme
## It would
have a lot of content of course
## Like code
`
const identity = x => x;
`
## And other stuff
of course !

View file

@ -1,12 +1,16 @@
import React, { PropTypes } from 'react';
import styles from './PublicFigureAvatar.css';
import cssModules from 'react-css-modules';
import styles from './PublicFigureAvatar.css';
const PublicFigureAvatar = ({ publicFigure }) => (
<div
styleName="wrapper"
style={{ backgroundUrl: !!publicFigure.picture ? publicFigure.picture.url : undefined }}
></div>
style={{
backgroundImage: !!publicFigure.picture
? `url(${publicFigure.picture.url})`
: undefined,
}}
/>
);
PublicFigureAvatar.propTypes = {
publicFigure: PropTypes.object.isRequired,

View file

@ -0,0 +1,26 @@
import React from 'react';
// eslint-disable-next-line no-unused-vars
import { storiesOf, action, linkTo } from '@kadira/storybook';
import { withKnobs, text, boolean, number } from '@kadira/storybook-addon-knobs';
import withReadme from 'storybook-readme/with-readme';
import PublicFigureAvatar from './';
import README from './README.md';
const stories = storiesOf('PublicFigureAvatar', module);
stories.addDecorator(withKnobs);
stories.addWithInfo(
'pony avatar',
'Description of the story',
withReadme(README,
() => (
<PublicFigureAvatar publicFigure={{ picture: { url: text('image url', 'http://tinyurl.com/jucz8b9') } }} />
)
)
);
stories.add('jake avatar', () => (
<PublicFigureAvatar publicFigure={{ picture: { url: 'http://tinyurl.com/jb286jq' } }} />
));

View file

@ -0,0 +1,8 @@
import React from 'react';
import { storiesOf, action, linkTo } from '@kadira/storybook';
import Identity from './';
storiesOf('Identity', module)
.add('simple text', () => (
<Identity>Hello</Identity>
));

2
stories/index.js Normal file
View file

@ -0,0 +1,2 @@
import '../src/components/general/Identity/stories.js';
import '../src/components/PublicFigureAvatar/stories.js';

52
webpack/loaders.js Normal file
View file

@ -0,0 +1,52 @@
const CONSTANTS = require('../webpack/constants');
const APP_PATH = CONSTANTS.APP_PATH;
const loaders = [
{
test: /\.jsx?$/,
loader: 'babel-loader',
exclude: /node_modules/,
},
{
test: /src.+\.css$/,
loader: 'style-loader'
+ '!css-loader'
+ '?modules&localIdentName=[name]__[local]___[hash:base64:5]'
+ '&importLoaders=1'
+ '!postcss-loader',
},
{
test: /node_modules.*\.css$/,
loader: 'style!css',
},
{
test: /\.(png|svg|gif|jpeg|jpg)$/,
include: APP_PATH,
loader: 'file?name=images/[name].[ext]',
},
{
test: /\.(eot|woff|ttf)$/,
include: APP_PATH,
loader: 'file-loader?name=fonts/[name].[ext]',
},
{
test: /\.(svg|woff2?)$/,
exclude: APP_PATH,
loader: 'url?limit=10000',
},
{
test: /\.(ttf|eot)$/,
exclude: APP_PATH,
loader: 'file',
},
{
test: /\.json$/,
loader: 'json',
},
{
test: /\.md$/,
loader: 'raw',
},
];
module.exports = loaders;

12
webpack/resolve.js Normal file
View file

@ -0,0 +1,12 @@
const path = require('path');
const CONSTANTS = require('./constants');
const APP_ROOT = CONSTANTS.APP_ROOT;
module.exports = {
alias: {
react: path.resolve(APP_ROOT, 'node_modules/react'),
},
modulesDirectories: ['src', 'web_modules', 'node_modules'],
extensions: ['', '.js', '.jsx'],
};

View file

@ -1,90 +1,23 @@
const path = require('path');
const webpack = require('webpack');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
// const CompressionPlugin = require('compression-webpack-plugin')
// const CopyWebpackPlugin = require('copy-webpack-plugin');
const postcssProcessors = require('./postcss-processors');
const loaders = require('./loaders');
const resolve = require('./resolve');
const CONSTANTS = require('./constants');
const APP_ROOT = CONSTANTS.APP_ROOT;
const APP_PATH = CONSTANTS.APP_PATH;
const APP_NAME = CONSTANTS.APP_NAME;
const SRC_FOLDER = CONSTANTS.SRC_FOLDER;
// Set-up common plugins
const plugins = [];
plugins.push(new webpack.NoErrorsPlugin()); // No assets emitted with errors
plugins.push(new ExtractTextPlugin('[name].[contenthash].css', { allChunks: false })); // Extract CSS to external style.css file
plugins.push(new HtmlWebpackPlugin({
template: `${SRC_FOLDER}/index.html`,
inject: true,
filename: 'index.html',
}));
plugins.push(new webpack.NoErrorsPlugin()); // No assets emitted with errors
module.exports = {
resolve: {
alias: {
react: path.resolve(APP_ROOT, 'node_modules/react'),
},
modulesDirectories: ['src', 'web_modules', 'node_modules'],
extensions: ['', '.js', '.jsx'],
},
entry: `${APP_PATH}/index.js`,
output: {
filename: `${APP_NAME}.[name].[hash].js`,
},
resolve,
plugins,
module: { loaders },
externals: {
TweenLite: 'TweenLite',
},
node: {
fs: 'empty',
},
plugins,
module: {
loaders: [
{
test: /\.jsx?$/,
loader: 'babel-loader',
exclude: /node_modules/,
},
{
test: /\.css$/,
loader: 'style-loader'
+ '!css-loader'
+ '?modules&localIdentName=[name]__[local]___[hash:base64:5]'
+ '&importLoaders=1'
+ '!postcss-loader',
exclude: /node_modules/,
},
{
test: /\.(png|svg|gif|jpeg|jpg)$/,
include: APP_PATH,
loader: 'file?name=images/[name].[ext]',
},
{
test: /\.(eot|woff|ttf)$/,
include: APP_PATH,
loader: 'file-loader?name=fonts/[name].[ext]',
},
{
test: /\.(svg|woff2?)$/,
exclude: APP_PATH,
loader: "url?limit=10000"
},
{
test: /\.(ttf|eot)$/,
exclude: APP_PATH,
loader: "file"
},
{
test: /\.json$/,
loader: 'json',
},
],
},
postcss: wp => postcssProcessors(wp),
};

View file

@ -1,4 +1,4 @@
const config = require('./webpack.base.config');
const config = require('./webpack.bundle.config');
const webpack = require('webpack');
const path = require('path');

View file

@ -1,5 +1,5 @@
const webpack = require('webpack');
const config = require('./webpack.base.config');
const config = require('./webpack.bundle.config');
const path = require('path');
const CopyWebpackPlugin = require('copy-webpack-plugin');

View file

@ -0,0 +1,21 @@
const config = require('./webpack.base.config');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CONSTANTS = require('./constants');
const APP_PATH = CONSTANTS.APP_PATH;
const APP_NAME = CONSTANTS.APP_NAME;
const SRC_FOLDER = CONSTANTS.SRC_FOLDER;
config.plugins.push(new HtmlWebpackPlugin({
template: `${SRC_FOLDER}/index.html`,
inject: true,
filename: 'index.html',
}));
config.entry = `${APP_PATH}/index.js`;
config.output = {
filename: `${APP_NAME}.[name].[hash].js`,
};
module.exports = config;

View file

@ -1,5 +1,5 @@
const webpack = require('webpack');
const config = require('./webpack.base.config');
const config = require('./webpack.bundle.config');
const path = require('path');
const CopyWebpackPlugin = require('copy-webpack-plugin');