Edited at

React + Storybook + styled-componentsをTypeScriptで動かす

More than 1 year has passed since last update.

設定するところが多く調べるところが多かったため、備忘録として書きます。


ツールのバージョン


@storybook/react

最新版を使いましょう。

"@storybook/react": "^4.0.0-alpha.9",


styled-components

自分がcssはstyled-componentsを使っていたので一応書いておきます。

これも最新版を使わないとエラーが発生しました。

"styled-components": "^3.3.2"


型定義ファイル

インストールしたものを抜粋します。


package.json

"devDependencies": {

"@types/jest": "^23.0.2",
"@types/react": "^16.3.17",
"@types/react-dom": "^16.0.6",
"@types/storybook__addon-actions": "^3.0.3",
"@types/storybook__addon-links": "^3.3.1",
"@types/storybook__addon-notes": "^3.3.1",
"@types/storybook__addon-storyshots": "^3.4.2",
"@types/storybook__react": "^3.0.7",
}


webpack.config.js

小さい構成なので以下のようになりました。


webpack.config.js

const path = require('path');

const env = process.env.NODE_ENV;

const config = {
mode: env || 'development',
target: 'node',
entry: {
index: [path.resolve(__dirname, 'src/index.js')],
},
output: {
path: path.resolve(__dirname, './public/'),
publicPath: './public/',
filename: '[name].js',
},
module: {
rules: [
{
test: /\.(ts|tsx)$/,
loader: 'babel-loader!awesome-typescript-loader',
},
],
},
resolve: {
extensions: ['.ts', '.tsx'],
},
};

module.exports = config;



storybook

storybook側も設定が必要です。


webpack

webpackの設定を追加します。


.storybook/webpack.config.js

const path = require("path");

module.exports = (baseConfig, env, defaultConfig) => {
defaultConfig.module.rules.push({
test: /\.(ts|tsx)$/,
include: path.resolve(__dirname, "../src"),
loader: require.resolve("awesome-typescript-loader")
});

// addon-storysource使うときだけ
defaultConfig.module.rules.push({
test: /\.stories\.jsx?$/,
loaders: [
{
loader: require.resolve("@storybook/addon-storysource/loader"),
options: { parser: "typescript" }
}
],
enforce: "pre"
});

defaultConfig.resolve.extensions.push(".ts", ".tsx");

return defaultConfig;
};



config.js

.ts.tsxの拡張子を持つファイルを対象にします。


.storybook/config.js

import React from 'react';

import { configure } from "@storybook/react";
const req = require.context("../src/Components", true, /.stories.(ts|tsx)$/);

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

configure(loadStories, module);



styled-components

テーマファイルを作成しつつ、モジュールをラップするようにしてTypeScriptに適用させます。

共通で使用するカラー変数などもここで設定することも可能です。


Theme/index.ts

import * as styledComponents from "styled-components";

export interface ThemeInterface {
primaryColor: string;
}

export const Theme = {
primaryColor: "#e9e9e9"
};

const {
default: styled,
css,
injectGlobal,
keyframes,
ThemeProvider
} = styledComponents as styledComponents.ThemedStyledComponentsModule<ThemeInterface>;

export default styled;
export { css, injectGlobal, keyframes, ThemeProvider };



Component

実際のコンポーネントは以下のようになります。

ポイントはnode_modulesからstyled-componentsを直接読み込まず、上で作成したTypeScriptに適用させたものを読み込むところです。


Caption/index.tsx

import * as React from "react";

import styled from "../Theme";

interface CaptionInterface {
children?: React.ReactChild;
}

const StyledCaption = styled.h1`
margin: 0 0 12px 0;
color: black;
font-size: 2rem;
font-weight: bold;
line-height: 1.4;
`
;
const Caption:React.SFC<CaptionInterface> = ({...props}) => <StyledCaption {...props} />;
export default Caption;


当然storybookも.tsxで作成します。


Caption/index.stories.tsx

import React from 'react';

import { storiesOf } from '@storybook/react';

import Caption from './index';

storiesOf('Atoms/Caption', module).add('default', () => <Caption>Caption is here!</Caption>);



おわり

多分これで動くと思います!

お役に立っていたら嬉しいです。