【StoryBook】Next.js + Tailwindcss + cssModule 環境でのStoryBook導入方法
概要
StoryBookとはフロントエンド開発において、様々なコンポーネントをアプリケーションから独立した状態でデザインや動作チェックなどを行い、さらにコンポーネント群をカタログ化して管理することのできる開発支援ツールです。
今回は、Next.js + Tailwindcss + cssModule の開発環境にStoryBookを導入する手順についてまとめました。
StoryBookインストール直後では、TailwindcssとcssModuleによるスタイルが適用されず、コンポーネントのデザインが全く確認できないため、その解決方法についても解説します。
導入手順
Next.js、Tailwindcss、cssModuleはインストール済の状態を前提として、StoryBookを追加で導入する方法を説明します。
StoryBookのインストール
次のコマンドでStoryBookに必要なライブラリ一式をインストールします。
npx sb init
インストール途中で"Do you want to run the 'eslintPlugin' fix on your project?
を聞かれます。ESLintを使用してコードを検査している方は、“y”を選択してeslint-plugin-storybookをインストールしておくと良いかもしれません。
設定ライブラリのインストール
次のコマンドでstorybook-css-modules-preset
ライブラリをインストールします。
これをインストールすることで、簡単にcssmoduleをStoryBookに適用することができるようになります。
npm install --save-dev storybook-css-modules-preset
ライブラリのWEB公式サイト
!()[https://www.npmjs.com/package/storybook-css-modules-preset]
Storybookの設定
- Storyファイルのパス指定
Storyファイルを格納するパスを設定します。各々の開発環境により、適宜ファイルパスを変えてください。
私の開発環境ではコンポーネント群を./components
フォルダ配下に格納しており、またStoryファイルもコンポーネントファイルと同階層に置くと決めたため、以下のような設定を追記しました。
stories: ["../components/**/*.stories.@(js|jsx|ts|tsx)",]
- cssModuleの適用
cssModuleでスタイル付けしたコンポーネントが、Storybook画面上でもスタイルが反映されるように設定を行います。
次のコマンドでstorybook-css-modules-preset
ライブラリをインストールします。
npm install --save-dev storybook-css-modules-preset
Storybookの設定ファイルに以下を追記します。
addons: ["storybook-css-modules-preset",]
- cssの適用
Next.jsにおいては、グローバルに適用するcssを./styles/global.css
に記述しており、またTailwindcssもこのファイルで読み込ませて、どのページからもtailwindのクラスを利用できるようにしているはずです。global.css
をStorybookに読み込ませる設定を行います。
まず、次のコマンドで公式のアドオンをインストールします。
npm install --save-dev @storybook/addon-postcss
Storybookの設定ファイルに以下を追記します。
addons: [
{
name: "@storybook/addon-postcss",
options: {
postcssLoaderOptions: {
implementation: require("postcss"),
},
},
},
],
import "../styles/globals.css";
設定結果
私の環境における設定結果を参考に以下に示します。
module.exports = {
stories: [
"../stories/**/*.stories.mdx",
"../stories/**/*.stories.@(js|jsx|ts|tsx)",
+ "../components/**/*.stories.@(js|jsx|ts|tsx)",
],
addons: [
"@storybook/addon-links",
"@storybook/addon-essentials",
"@storybook/addon-interactions",
+ "storybook-css-modules-preset",
+ {
+ name: "@storybook/addon-postcss",
+ options: {
+ postcssLoaderOptions: {
+ implementation: require("postcss"),
+ },
+ },
+ },
],
framework: "@storybook/react",
core: {
builder: "@storybook/builder-webpack5",
},
};
+ import "../styles/globals.css";
export const parameters = {
actions: { argTypesRegex: "^on[A-Z].*" },
controls: {
matchers: {
color: /(background|color)$/i,
date: /Date$/,
},
},
};
StoryBooksの起動
次のコマンドでStorybookを起動します。
npm run storybook
Storybookの起動後、ブラウザからhttp://localhost:6006/
にアクセスするとStoryboookの画面が表示されます。EXAMPLEとして最初から登録されている、ButtonやHeaderなどのコンポーネントが確認できると思います。
自作のコンポーネントを登録してみる。
自作の汎用ボタンコンポーネントに対してStoryファイルを作成し、Storybookの画面上に表示されるまでの例を示します。
サンプルコード
- まずはコンポーネント本体です
import { ReactNode } from "react";
import styles from "./Button.module.css";
type Props = {
children: ReactNode;
disabled?: boolean;
styleType: "primary" | "secondary" | "danger" | "disabled";
onclick?: () => void;
};
/**
* 共通Buttonコンポーネント
* @param children コンポーネントで内包している子要素
*/
const Button = (props: Props) => {
const { onclick, children, disabled, styleType } = props;
// カラー切替
let style = styles.primary;
if (styleType === "secondary") {
style = styles.secondary;
} else if (styleType === "danger") {
style = styles.danger;
} else if (styleType === "disabled") {
style = styles.disabled;
}
return (
<button className={style} onClick={onclick} disabled={disabled}>
{children}
</button>
);
};
export default Button;
- cssModuleによるスタイルです
Tailwindcssでがっつりスタイル付けしています。
.primary {
@apply inline-block py-2 px-10 text-sky-500 hover:text-gray-50 bg-gray-50 hover:bg-sky-500 border-2 border-sky-500 rounded-full shadow-sm font-semibold transition duration-300;
}
.secondary {
@apply inline-block py-2 px-10 text-indigo-400 hover:text-gray-50 bg-gray-50 hover:bg-indigo-400 border-2 border-indigo-400 rounded-full shadow-sm font-semibold transition duration-300;
}
.danger {
@apply inline-block py-2 px-10 text-red-500 hover:text-gray-50 bg-gray-50 hover:bg-red-500 border-2 border-red-500 rounded-full shadow-sm font-semibold transition duration-300;
}
.disabled {
@apply inline-block py-2 px-10 text-gray-400 bg-gray-50 border-2 border-gray-400 rounded-full shadow-sm font-semibold transition duration-300;
}
- コンポーネントに対するStoryファイルです。
Storyファイルの記述方法についてはGoogleで検索すると多くの良記事が出てきますので、ここでは割愛します。
import { ComponentMeta, ComponentStoryObj } from "@storybook/react";
import Button from "./Button";
export default {
title: "Molecules/Button",
component: Button,
} as ComponentMeta<typeof Button>;
export const Primary: ComponentStoryObj<typeof Button> = {
args: {
children: "button text",
disabled: false,
styleType: "primary",
},
};
export const Secondary: ComponentStoryObj<typeof Button> = {
args: {
children: "button text",
disabled: false,
styleType: "secondary",
},
};
export const Danger: ComponentStoryObj<typeof Button> = {
args: {
children: "button text",
disabled: false,
styleType: "danger",
},
};
export const Disabled: ComponentStoryObj<typeof Button> = {
args: {
children: "loading ...",
disabled: true,
styleType: "disabled",
},
};
デモ
上記サンプルコードの動作デモになります。
まとめ
Next.js + Tailwindcss + cssModule の開発環境にStoryBookを導入する手順についてまとめました。
StorybookにTailwindcssとcssModuleを読み込ませる方法がやや難しいポイントでした。Googleで検索するといろいろな対処方法が出てくるのですが、これが一番簡単な方法かと思います。
バージョン
本記事執筆時の関連ライブラリのバージョンを貼っておきます。
"next": "12.2.3",
"tailwindcss": "^3.1.6",
"@storybook/addon-actions": "^6.5.10",
"@storybook/addon-essentials": "^6.5.10",
"@storybook/addon-interactions": "^6.5.10",
"@storybook/addon-links": "^6.5.10",
"@storybook/addon-postcss": "^2.0.0",
"@storybook/builder-webpack5": "^6.5.10",
"@storybook/manager-webpack5": "^6.5.10",
"@storybook/react": "^6.5.10",
"@storybook/testing-library": "^0.0.13",
参考文献
Discussion