Storybook導入メモ(with React)

# 3行で
- 汎用的に使えそうなReactコンポーネントをつくった
- どこで使えるのかよくわからない感じになってしまった
- Storybookでカタログを作ろう

# Storybookとは
<img width="1175" alt="スクリーンショット 2018-01-30 19.38.46.png" src="https://qiita-image-store.s3.amazonaws.com/0/11316/92622d81-f630-ea14-0099-92c3ac8535c1.png">

- [Storybook \- UI dev environment you'll love to use](https://storybook.js.org/)

コンポーネントのカタログみたいなやつを表示してくれるツール。コマンドを叩くとコンポーネントをいい感じに表示してくれるサーバーが起動するので、ウェブブラウザで自分たちの作ったReactコンポーネントのカタログを見れるようにできます。

# 背景
Storybook導入を考える前はwikiで管理しようとしてたけど挫折しました。Storybookいいよという話を聞いて、見てみたらたしかによさそうという感想を持ったので試してみた次第です。

# はじめかた

## getstorybookコマンドを叩く
Storybookのトップページにあるように、以下でできます。

```bash

npm i -g @storybook/cli
cd my-react-app
getstorybook
```

自分のプロジェクトのディレクトリ直下で `getstorybook` コマンドを叩くだけで、storybookの設定を勝手に作ってくれるので何も考える必要がない。補足しておくと、具体的には設定ファイルなどを作って、 `package.json` にコマンドを追加してくれています。

その場で以下を打つとサーバーが立ち上がります。

```bash
npm run storybook
```


# コンポーネントを置く
`getstorybook` するとデモのコンポーネントが置かれた状態でstorybookサーバーのようなものが動くので、それを真似てコンポーネントを置けばよさそう。置いてみます。

```js:my-react-app/stories/index.stories.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';
import LikeButton from '../app/javascript/components/common/LikeButton';

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

// デモで最初から置かれているやつ
storiesOf('Button(Demo)', module)
  .add('with text', () => <Button onClick={action('clicked')}>Hello Button</Button>)
  .add('with some emoji', () => <Button onClick={action('clicked')}>😀) 😎😀 👍😎 💯👍</Button>);

// 上のデモを真似て追加
storiesOf('LikeButton', module)
  .add('いいね済み, 10いいね', () => {
    return (
      <LikeButton
        liked={true}
        likeCount={10}
        onLike={() => {} }
        onUnlike={() => {} }
      />
    );
  });
```

<img width="678" alt="スクリーンショット 2018-01-30 17.34.44.png" src="https://qiita-image-store.s3.amazonaws.com/0/11316/d66b13b2-9079-c4e5-aaba-e30dd71b0e2b.png">

うまくいってる感じはしませんが、一応サイドバーに追加されてクリックしたらそれが表示されるという状態にはなりました。

# 静的ファイル配信
うまくいってる感じがしないのは、画像が入っておらず、またCSSがコンポーネントに当たっていないからです。どちらもドキュメントに書いてあるようなので、それを見て直します。



## 画像

- [Serving Static Files](https://storybook.js.org/configurations/serving-static-files/)

画像については、今回はコンポーネントが参照するアイコン画像が `./public` にあるという感じだったので、上にも書かれている通り `package.json` を以下のように修正するだけで大丈夫でした。

```diff:package.json
- start-storybook -p 6006
+ start-storybook -s ./public -p 6006
```

再び `npm run storybook` し直すと、うまく表示されました。

<img width="649" alt="スクリーンショット 2018-01-30 17.41.59.png" src="https://qiita-image-store.s3.amazonaws.com/0/11316/e64e423b-1ab8-1e2c-a549-d2cfbfb53817.png">

## CSS
<img width="725" alt="スクリーンショット 2018-01-30 17.50.13.png" src="https://qiita-image-store.s3.amazonaws.com/0/11316/7c61e4da-d7c6-7c11-3fa2-1fab51e8f501.png">

次に、CSSです。コンポーネントの中にスタイルが閉じていればいいのですが、Bootstrap 3のようなCSSフレームワークでデザインを実現しているような場合は、そのCSSをどうにかして当てる必要があります。

[Add Custom Head Tags](https://storybook.js.org/configurations/add-custom-head-tags/)に書かれているように、 `preview-head.html` というファイルでheadタグに追加したいHTMLを書けば良さそうです。今回はCSSのダウンロードなので、Bootstrapや独自のスタイルも諸々入った `application.css` があるとしたら、それをlinkタグで読み込めばOKです。

```html:.storybook/preview-head.html
<link rel="stylesheet" media="all" href="/assets/application.css" />
```

![2ed7c3155cc416fab82712d92f16c996.gif](https://qiita-image-store.s3.amazonaws.com/0/11316/6d2ab87e-7d5f-5308-4262-cf446f857473.gif)

意図した通りにスタイルが反映されました。

# まとめ

この要領でコンポーネントを並べていけば、「なんか使えるコンポーネントあるかな〜」というのがざっくり確認できるのではないでしょうか。ほかにもできることはありそうなので、模索しながらこちらにも追記していこうかと思っています。