StoryBook（React）最初の1歩


storybookのセットアップがnpxを使う方法に代わってたのでメモ

wrote: 2019.1.9


# install

以下、reactベースで進めるのでcreate-react-app を入れておく

```
npm i -g create-react-app 
```

入った事を以下コマンドで確かめる。バージョン番号が表示されればOK

```
> create-react-app --version
2.1.3
```

## プロジェクト作成

### Reactプロジェクト作成

まずはベースとなるReactプロジェクトを作成する。
storybook2という名称で作成する。

```shell
create-react-app storybook2
```

### Storybookを入れる

```shell
cd storybook2
npx -p @storybook/cli sb init
```


## Storybook実行

```shell
yarn storybook
```

 以下のような画面が出ればOK。

![image](https://qiita-image-store.s3.amazonaws.com/0/49910/6b42e92c-9b21-c152-3918-53376ec29a0b.png)



# Story設定ファイル 

表示されたStory画面の設定は`src/stories/index.js`にあります。
以下、便宜上、①と②表記を追加しました。

```js:index.js
import React from 'react';

import { storiesOf } from '@storybook/react';
import { action } from '@storybook/addon-actions';
import { linkTo } from '@storybook/addon-links';

import { Button, Welcome } from '@storybook/react/demo';

// ①
storiesOf('Welcome', module).add('to Storybook', () => <Welcome showApp={linkTo('Button')} />);

//②
storiesOf('Button', module)
  .add('with text', () => <Button onClick={action('clicked')}>Hello Button</Button>)
  .add('with some emoji', () => (
    <Button onClick={action('clicked')}>
      <span role="img" aria-label="so cool">
        😀 😎 👍 💯
      </span>
    </Button>
  ));
```



## 解説

### ①部分

```js:index.js
storiesOf('Welcome', module).add('to Storybook', () => <Welcome showApp={linkTo('Button')} />);
```

Storybook画面で表示される左サイドメニュー・Welcomeタブに`to Storybook`項目を追加する。
追加内容は、`@storybook/react/src/demo/Welcome.js`で定義された`Welcomeコンポーネント`を使う。
`Welcomeコンポーネント`にはshowAppという引数が設定されているので、showAppに対して`linkTo('Button')`を渡す。


### ②部分

```js:index.js
storiesOf('Button', module)
  .add('with text', () => <Button onClick={action('clicked')}>Hello Button</Button>)
```

Storybook画面で表示される左サイドメニュー・Buttonタブに`'with text`項目を追加する。

追加内容は、`@storybook/react/src/demo/Button.js`で定義された`Buttonコンポーネント`を使う。
`Buttonコンポーネント`には `children` `onClick` 引数が設定されている。
onClickに対して`@storybook/addon-actions`の`action('clicked')`を渡す。
childrenに対して `Hello Button` を渡す。


```js:index.js
  .add('with some emoji', () => (
```

も同様である。



## コンポーネントのStorybookへの追加

Custom Button を作成する


./src/components/の下に ButtonCustom.jsを作成し、
`./node_modules/@storybook/react/src/demo/Button.js`の内容をコピーします。

ついでに属性もちょっと変えてみます。
以下の例では背景色を青に、文字色を白に変えました。

```js:ButtonCustom.js
import React from "react";
import PropTypes from "prop-types";

const styles = {
  border: "1px solid #eee",
  borderRadius: 3,
  backgroundColor: "#3498db",
  cursor: "pointer",
  fontSize: 15,
  padding: "3px 10px",
  color: "#fff",
  margin: 10
};

const Button = ({ children, onClick }) => (
  <button onClick={onClick} style={styles} type="button">
    {children}
  </button>
);

Button.displayName = "ButtonCustom";
Button.propTypes = {
  children: PropTypes.node.isRequired,
  onClick: PropTypes.func
};
Button.defaultProps = {
  onClick: () => {}
};

export default Button;
```



### ButtonCustomを使う

src/stories/index.js　を編集します。

importを追加。

```js:src/stories/index.js
import ButtonCustom from '../components/ButtonCustom';
```

storiesOfを追加します。

```js:src/stories/index.js
storiesOf("ButtonCustom", module).add("blue back", () => (
  <ButtonCustom onClick={action("clicked")}>Hello Button</ButtonCustom>
));
```

保存してブラウザをリロードします。
以下のようにButtonCustomコンポーネントが表示されればOK

![image](https://qiita-image-store.s3.amazonaws.com/0/49910/86fcde45-7111-5be9-5f7c-abb9d34a2937.png)


## ButtonCustomの色を変更可能にする


CSSを変更できるボタンコンポーネントを作成します。


```js:ButtonCustomBackgroundColor.js
import React from "react";
import PropTypes from "prop-types";

const styles = backgroundColor => ({
  border: "1px solid #eee",
  borderRadius: 3,
  backgroundColor: backgroundColor ? backgroundColor : "#3498db",
  cursor: "pointer",
  fontSize: 15,
  padding: "3px 10px",
  color: "#fff",
  margin: 10
});

const Button = ({ children, onClick, backgroundColor }) => (
  <button onClick={onClick} style={styles(backgroundColor)} type="button">
    {children}
  </button>
);

Button.displayName = "ButtonCustom";
Button.propTypes = {
  children: PropTypes.node.isRequired,
  onClick: PropTypes.func
};
Button.defaultProps = {
  onClick: () => {}
};

export default Button;
```

以下のようにbackgroundColorを指定したタグをストーリーに追加します。

```js
    <ButtonCustomBackgroundColor
      onClick={action("clicked")}
      backgroundColor="#ff0000"
    >
```

以下のようになります。

```js:src/stories/index.js
storiesOf("ButtonCustom", module)
  .add("blue back", () => (
    <ButtonCustom onClick={action("clicked")}>Hello Button</ButtonCustom>
  ))
  .add("red back", () => (
    <ButtonCustomBackgroundColor
      onClick={action("clicked")}
      backgroundColor="#ff0000"
    >
      Button1
    </ButtonCustomBackgroundColor>
  ))
  .add("green back", () => (
    <ButtonCustomBackgroundColor
      onClick={action("clicked")}
      backgroundColor="#00ff00"
    >
      Button2
    </ButtonCustomBackgroundColor>
  ));
```




## 結果

３種類のボタンが出るようになりました。

![image](https://qiita-image-store.s3.amazonaws.com/0/49910/607eed94-ab29-9430-a472-c122455fbc46.png)
![image](https://qiita-image-store.s3.amazonaws.com/0/49910/a119f16e-06d5-dc98-2550-d4a9027bc178.png)
![image](https://qiita-image-store.s3.amazonaws.com/0/49910/bc45c134-c1d5-719b-41fa-619d85457f92.png)


# ソース

今回のソースは以下に保管しました。

[sugasaki/storybook-react-firststep1](https://github.com/sugasaki/storybook-react-firststep1)

# おまけ

## IE11対応

`@babel/polyfill`を入れる

```shell
yarn add @babel/polyfill
```

`.storybook/addons.js`の先頭に以下を追記

```js:.storybook/addons.js
import "@babel/polyfill";
```

参考

[Storybook not working in IE11 · Issue #4099 · storybooks/storybook](https://github.com/storybooks/storybook/issues/4099#issuecomment-428190677)