EzDev.org

storybook

storybook - Interactive development & testing environment for React, React-Native, Vue UI components


import scss file with Storybook

I'm currently facing an issue with Storybook. Everything is working great in my app, with webpack. Storybook seems to have issue with my configuration.

Here's my webpack.config.js :

module.exports = {
   entry: './index.js',
   output: {
   path: path.join(__dirname, 'dist'),
   filename: 'bundle.js'
},
module: {
   loaders: [
   {
      test: /\.js$/,
      loader: 'babel-loader',
      exclude: /node_modules/,
      include: __dirname
   },
   {
      test: /\.scss$/,
         use: [
         {loader: "style-loader"}, 
         {loader: "css-loader"},
         {loader: "sass-loader",
          options: {
            includePaths: [__dirname]
    }
  }]
},

Storybook have issue with parsing the scss file, do I need to create a specific webpack.config.js for Storybook to solve this?

In my main app I'm importing my scss file this way : import './styles/base.scss'


Source: (StackOverflow)

Storyshots jest - Cannot find module '@storybook/react' from 'index.js'

I am trying to incorporate storyshots in my project. I have this jest config:

"moduleFileExtensions": [
  "json",
  "js",
  "jsx"
],

Here is my test file content:

import React from 'react';
import renderer from 'react-test-renderer';
import initStoryshots from '@storybook/addon-storyshots';

import IconCell from './';
initStoryshots({
    framework: 'react'
});
test('iconcell', () => {
    expect(renderer.create(<IconCell size="normal" type="pause" />).toJSON()).toMatchSnapshot();
});

But it throws error:

Cannot find module '@storybook/react' from 'index.js'

The error thrown in node_modules/jest-resolve/build/index.js


Source: (StackOverflow)

How add react-relay component to the storybook?

I am trying create a storybook for my react-realy app, but i don't know how to set mockup data for that component. For simple a component it is ok, because i can use dummy UI component vs Container approach, but i can't use this for nested relay components, for example there is a UserList component, which i want add to storybook, i can split relay fragment part to container and UI part to the component, but what if UserList children are too relay component? I can't split their when they are a part of the composition of UserList?

Is there some solution for add relay components to the storybook?


Source: (StackOverflow)

What's the right way to configure React Storybook to respect Webpack's context field for relative imports?

consider:

src/
|_ components
  |_ thing // import tool from 'utils' <--- not relative ('../utils'), fancy webpack context/resolve trick
|_ utils/
  |_ tool

webpack allows you to fake relative imports like so:

context: path.resolve(__dirname, "src")

This allows you to write all imports in src/ as if they alias to node_modules without having to manually crawl ../../../../../.......

Using this in my app's webpack config is easy.

When I try to use the same trick in storybook's webpack config, so that it doesn't choke on my tricky imports, I get errors like this:

Error in ./src/components/thing
Module not found: Error: Can't resolve 'utils' in 'src/components/thing'

Is there any good way to accomplish this?


Source: (StackOverflow)

How to update components props in storybook

I am using storybook (this) to play with my components in isolation. I want to mock all the flux cycle (that in the full app it is done with the help of redux) and update a property using a simple object in the story, but I am missing something.

  storiesOf('Color picker', module).add('base', () => {
    let colorPickerState = {
      changeColor: function(data) {
        this.color = data.color
      },
      color: '#00aced'
    }
    return (
      <ColorPicker
        name="color"
        onChange={colorPickerState.changeColor.bind(colorPickerState)}
        value={colorPickerState.color}
      />
    )
  }

I expect the value prop of <ColorPicker /> to be updated when the onChange is called; I can see the value of colorPickerState.color being updated correctly, but the component does not re-render.

What am I missing?


Source: (StackOverflow)

Storybook + Font Files

I can't seem to get Storybook's webpack to compile my CSS. It throws up on the font files and tells me I may need a loader, but I've added one to the webpack.config.js file it's using.

Here is my webpack.config.js:

const resolve = require('path').resolve;

module.exports = {
  module: {
    loaders: [
      {
        test: /\.css$/,
        loaders: ['style', 'css', 'postcss?modules'],
        include: resolve(__dirname, '../')
      },
      {
        test: /\.(png|woff|woff2|eot|ttf|svg)$/,
        loaders: ['file'],
        include: resolve(__dirname, '../')
      }
    ]
  }
};

I have the loader and it sees it, but it still gives me errors like this:

ERROR in ./~/font-awesome/fonts/fontawesome-webfont.svg?v=4.7.0
Module parse failed: /home/dcpdev/projects/my-project/node_modules/font-awesome/fonts/fontawesome-webfont.svg?v=4.7.0 Unexpected token (1:0)
You may need an appropriate loader to handle this file type.
SyntaxError: Unexpected token (1:0)
    at Parser.pp$4.raise (/home/dcpdev/projects/my-project/node_modules/webpack/node_modules/acorn/dist/acorn.js:2221:15)
    at Parser.pp.unexpected (/home/dcpdev/projects/my-project/node_modules/webpack/node_modules/acorn/dist/acorn.js:603:10)
    at Parser.pp$3.parseExprAtom (/home/dcpdev/projects/my-project/node_modules/webpack/node_modules/acorn/dist/acorn.js:1822:12)
    <snip>

I get one of those errors for each extension (eot, woff, woff2, ttf, svg).

I know it's reading that webpack.config.js file, because if I do something like change to a nonsensical loader name (like cake), I get an error from it.

Also, the file is in a storybook directory off the root of my project, so resolve(__dirname, '../') should put it at the root of my project as well.

What am I missing?


Source: (StackOverflow)

Redux + storybook throws warning about changing store on the fly even with module.hot implemtended

I'm using storybook and I want to add redux as decorator. Whe running storybook, I got warning in console:

<Provider> does not support changing `store` on the fly. It is most likely that you see this error because you updated to Redux 2.x and React Redux 2.x which no longer hot reload reducers automatically. See https://github.com/reactjs/react-redux/releases/tag/v2.0.0 for the migration instructions.

It's my code for config storybook:

/* eslint-disable import/no-extraneous-dependencies, import/no-unresolved, import/extensions */

import React from 'react';
import { configure, storiesOf } from '@storybook/react';
import { Provider as ReduxProvider } from 'react-redux';
import forEach from 'lodash/forEach';
import unset from 'lodash/unset';
import Provider from 'components/Provider';
import initStore from 'utils/initStore';
import messages from '../lang/en.json';

const req = require.context('../components', true, /_stories\.js$/);

const ProviderDecorator = (storyFn) => {
  const TheProvider = Provider(() => storyFn());

  return (
    <ReduxProvider store={initStore()}>
      <TheProvider key={Math.random()} now={1499149917064} locale="en" messages={messages} />
    </ReduxProvider>
  );
}

function loadStories() {
  req.keys().forEach((filename) => {
    const data = req(filename);

    if (data.Component !== undefined && data.name !== undefined && data.stories !== undefined) {
      const Component = data.Component;

      const stories = storiesOf(data.name, module);

      stories.addDecorator(ProviderDecorator);

      let decorator = data.stories.__decorator;

      if (data.stories.__decorator !== undefined) {
        stories.addDecorator((storyFn) => data.stories.__decorator(storyFn()));
      }

      forEach(data.stories, (el, key) => {
        if (key.indexOf('__') !== 0) {
          stories.add(key, () => (
            <Component {...el} />
          ));
        }
      });
    } else {
      console.error(`Missing test data for ${filename}!`)
    }

  });
}

configure(loadStories, module);

and initStore file:

import { createStore, applyMiddleware } from 'redux';
import { composeWithDevTools } from 'redux-devtools-extension';
import thunkMiddleware from 'redux-thunk';
import { persistStore, autoRehydrate } from 'redux-persist';

import reducers from 'containers/redux/reducers';

export default () => {
  const store = createStore(
    reducers,
    {},
    composeWithDevTools(applyMiddleware(thunkMiddleware), autoRehydrate()),
  );

  if (module.hot) {
    // Enable Webpack hot module replacement for reducers
    module.hot.accept('../containers/redux/reducers', () => {
      const nextReducers = require('../containers/redux/reducers'); // eslint-disable-line global-require
      store.replaceReducer(nextReducers);
    });
  }

  persistStore(store);

  return store;
};

So as you can see I followed instructions from link in warning. What have I done wrong and how can I remove this warning? I know it won't show on production server, but it's pretty annoying in dev mode. :/


Source: (StackOverflow)

react storybook addon knobs not showing

I cant seem to be getting the @storybook addon knobs working? It doesnt seem to be decorating the actual story. Pretty much followed this

My code below.. Im using getstorybook with create-react-app

Using below packages:

@storybook/addon-actions": "^3.1.2,
@storybook/addon-info": "^3.1.4,
@storybook/addon-knobs": "^3.1.2,
@storybook/react": "^3.1.3

my setup

//.storybook/addons.js
import '@storybook/addon-knobs/register'

//.config
import { configure, setAddon, addDecorator } from '@storybook/react';
import infoAddon from '@storybook/addon-info';

setAddon(infoAddon);

function loadStories() {
  require('../stories');
}

configure(loadStories, module);

//stories/index.js
import React from 'react';
import { withKnobs, text, boolean, number } from '@storybook/addon-knobs';
import { storiesOf } from '@storybook/react';

const stories = storiesOf('Storybook Knobs', module);

  // Add the `withKnobs` decorator to add knobs support to your stories.
  // You can also configure `withKnobs` as a global decorator.
  stories.addDecorator(withKnobs);

  // Knobs for React props
  stories.add('with a button', () => (
    <button disabled={boolean('Disabled', false)} >
      {text('Label', 'Hello Button')}
    </button>
  ))

This should be a no brainer, but no suck luck.


Source: (StackOverflow)

How to pass props to component's story?

I wanted to add some stories for vue-select component using Storybook, but I'm struggling with more complicated cases, which involve passing props or methods.

When I pass props inside the template it works:

storiesOf('VSelect', module)
.add('with labeled custom options', () => ({
        components: {VSelect},
        template:   `<v-select :options='[{value: "CA", label: "Canada"}, {value: "UK", label: "United Kingdom"}]' />`
    }))

I find it not very readable, so I wanted to pass them separately as props or data:

.add('with labeled custom options as props', () => ({
        components: {VSelect},
        props:      {options: [{value: "CA", label: "Canada"}, {value: "UK", label: "United Kingdom"}]},
        data:       {options: [{value: "CA", label: "Canada"}, {value: "UK", label: "United Kingdom"}]},
        template:   `<v-select />`
    }))

but neither data, nor props are not recognized by storybook - they seem to be ignored.


Source: (StackOverflow)

fixed-data-table the width doesn't adjust container

I have a simple fixed-data-table component, based on this example I render it on storybook

import React, { Component } from 'react';
var FixedDataTable = require('fixed-data-table');
const {Table, Column, Cell} = FixedDataTable;

export default class IndexPage extends Component{
    render() {      
        return (
            <div className='container'>             
                <div className='row'>
                    <div className='col-md-2'></div>
                    <div className='col-md-8'>
                        <Table
                            rowHeight={50}
                            headerHeight={50}
                            rowsCount={3}
                            width={1000}
                            height={500}
                            {...this.props}>
                            <Column
                              header={<Cell>Col 1</Cell>}
                              cell={<Cell>Column 1 static content</Cell>}
                              width={200}
                              flexGrow={1}
                              fixed={true}
                            />
                            <Column
                              header={<Cell>Col 2</Cell>}
                              cell={<Cell>Column 2 static content</Cell>}
                              width={200}
                              flexGrow={1}
                            />
                            <Column
                              header={<Cell>Col 3</Cell>}
                              cell={<Cell>Column 3 static content</Cell>}
                              width={200}
                              flexGrow={1}
                            />
                        </Table>
                    </div>    
                    <div className='col-md-2'></div>
                </div>
            </div>  
        );  
    }
}

The problem is: The horizontal scroll of the table doesn't appear and the table goes out of the container's boundaries.


Source: (StackOverflow)

How to pass function to component's story?

I wanted to add some stories for vue-select component using Storybook, but I'm struggling with more complicated cases, which involve passing methods.

The method set directly in my components works (it fires alert('default')):

<template>
    <v-select :on-change="onchangecallback"
              :multiple="multiple"
              v-model="selected" :options="options"></v-select>
</template>

<script>
    import Vue from 'vue'
    import vSelect from 'vue-select'

    Vue.component('v-select', vSelect);

    export default {
        props: {
            options: {
                default: function() { return ['one', 'two'] },
                type: Array
            },
            multiple: {
                default: false,
                type: Boolean
            },
            onchangecallback: {
                default: () => {alert('default')},
                type: Function
            }
        },
        data() {
            return {
                selected: null
            }
        }
    }
</script>

but I want to overwrite onchangecallback function at one specific story (to fire alert('custom')), so I add to my play/index.js:

storiesOf('VSelect', module)
.add('onchangeCallback', () => ({
        components: {VSelect},
        template:   `<v-select />`,
        methods:    {
            onchangecallback: function() {
                // not sure if I need a function returning a function, so I use both
                alert('custom'); // never fired

                return function() {
                    alert('custom'); // never fired
                };
            }
        }
    }))

but I still end up with alert('default') instead alert('custom'), so onchangecallback is not overwritten.

At this point I don't even know if I'm passing this method correctly, the way it's designed is so counter-intuitive. I.e. in my component (first code snippet) I export onchangecallback in props (and it works) but in Storybook example methods are passed not in props but in methods!


Source: (StackOverflow)

React-native doesn't show storybook elements

I open new react-native v0.49 project and install storybook with command

npm i -g @storybook/cli

then i open my project and run

getstorybook

I see storybook modules in my project

    {
  "name": "materialApp",
  "version": "0.0.1",
  "private": true,
  "scripts": {
    "start": "node node_modules/react-native/local-cli/cli.js start",
    "test": "jest",
    "storybook": "storybook start -p 7007"
  },
  "dependencies": {
    "react": "16.0.0-beta.5",
    "react-native": "0.49.3"
  },
  "devDependencies": {
    "babel-jest": "21.2.0",
    "babel-preset-react-native": "4.0.0",
    "jest": "21.2.1",
    "react-test-renderer": "16.0.0-beta.5",
    "@storybook/react-native": "^3.2.13",
    "@storybook/addon-actions": "^3.2.13",
    "@storybook/addon-links": "^3.2.13",
    "react-dom": "16.0.0-beta.5",
    "prop-types": "^15.6.0"
  },
  "jest": {
    "preset": "react-native"
  }
}

when i run npm run storybook i see enter image description here

then i connect the server to react-native app by

adb reverse tcp:7007 tcp:7007

and I run react-native app by

react-native run-android

but I don't see any elements in the server enter image description here


Source: (StackOverflow)

How to properly use external state in react/storybook

I am using the great storybook/react, but I have encountered a problem.

I have a lot of components that rely on props (are stateless), so in my real-world app I have containers components that keep state.

For example, I have a <Toggle />, as you can see here that get value from its parent and calls the onChange from its props to change it. I want to have this behavior in my storybook, but don't how to do it:

storiesOf('Toggle', module).add('', () => (
  <Toggle name="toggle" checked={/*  what here ? */} onChange={/* what here ? */} />
))

Source: (StackOverflow)

React Native: Link Two Projects

I am just starting out with React Native for a new app.

I have broken down the project into components. I have used Storybook to create these components (a reat-native project).

I want to maintain this components project as a separate repo that can be used with my main project as well as other projects.

When I create my main project how, do I import the components that I have already been created in the from the 'components project' into my main project? Is there a way to link the two react native apps?


Source: (StackOverflow)

Default export works on the development site, but returns undefined in Storybook

So I'm building some component stubs for a new project I'm making. To see the visuals for these components I'm using Storybook. I have two separate webpack configs for the Storybook build and the regular build. Both inherit from a base config, shown below (I've removed some irrelevant loaders to make reading easier):

const path = require('path')

const config = {
  output: {
    filename: '[name].js',
    path: path.join(__dirname, 'public/js')
  },

  module: {
    rules: [
      {
        test: /\.jsx?$/,
        loader: 'babel-loader',
        exclude: /node_modules/,
        query: {
          presets: ['es2015', 'react'],
          plugins: [
            'transform-object-rest-spread',
            'transform-es2015-destructuring',
            ["react-css-modules", {
              "filetypes": {
                ".scss": {
                  "syntax": "postcss-scss",
                  "plugins": ["postcss-nested"]
                }
              },
              "generateScopedName": "[local]_[hash:base64:5]"
            }]
          ]
        }
      }
    ]
  },

  resolve: {
    modules: ['node_modules', path.join(__dirname, 'resources/assets/js')],
  }
}

module.exports = config

My Storybook config and my regular config differ like this:

Webpack.config.js

const path = require('path')
const webpack = require('webpack')
const UglifyJSPlugin = require('uglifyjs-webpack-plugin')
const webpackBaseConfig = require(path.join(__dirname, 'webpack.base.config.js'))

const plugins = [
  new webpack.optimize.CommonsChunkPlugin({
    name: 'vendor',
    minChunks: Infinity,
  }),
]

if(process.env.NODE_ENV === 'production') {
  plugins.push(new UglifyJSPlugin())
}

const webpackConfig = Object.assign(webpackBaseConfig, {
  entry: {
    vendor: ['react', 'react-dom', 'react-redux', 'react-router', 'react-router-dom', 'redux-form', 'axios', 'redux'],
    app: path.join(__dirname, 'resources/assets/js/app.jsx'),
  },

  plugins,
})

module.exports = webpackBaseConfig

Webpack.storybook.config.js

const path = require('path')
const webpackBaseConfig = require(path.join(__dirname, '../webpack.base.config.js'))

const storyBookConfig = Object.assign(webpackBaseConfig, {
  entry: path.join(__dirname, '../resources/assets/js/app.jsx'),
})

module.exports = storyBookConfig

Now everything works fine when I use the normal build, but when I visit storybook these components seems to break it:

components/AppHeader/AppHeader.component.jsx

import React from 'react'

import { Logo, UserCard } from 'components'

import './AppHeader.scss'

const AppHeader = (props) => {
  const { user } = props

  return (<div styleName="app-header">
    <Logo />
    <span styleName="user-profile">
      <UserCard firstName={user.firstName} lastName={user.lastName} />
    </span>
  </div>)
}

export default AppHeader

components/AppHeader/AppHeader.container.jsx

import { connect } from 'react-redux'

import AppHeader from './AppHeader.component.jsx'

const mapStateToProps = (state) => ({
  user: state.currentUser,
})

export default connect(
  mapStateToProps
)(AppHeader)

The error I get is when exporting the connected component in AppHeader.container.jsx:

Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in.

So it seems as if the default export in AppHeader.component.jsx is undefined? This is what makes me think that it's a problem with the webpack configuration for Storybook, because the container/component combo works when I view it not in Storybook.

Any suggestions/help would be greatly appreciated, thank you :)


Source: (StackOverflow)