この文書では、Next.js のプロジェクトに Storybook を追加して利用する方法を紹介します。Storybook を利用すると、事前に用意したデータを利用してコンポーネントを表示することができるため、プログラムの開発と並行してコンポーネントの UI を作成していくことができます。
プロジェクトの作成
まず最初に、Next.js のプロジェクトを作成し、続いて Storybook のインストールをします。
Next.js のプロジェクトの作成
プロジェクトの作成として、Next.js + Tailwind CSS のプロジェクトを作成します。

なお、標準のテンプレートで表示される postcss.config.mjs の設定では Storybook のインストールの時にエラーが表示されます。作成時のファイルは以下のようになっています。
これを以下のように書き換えてください。
上記の変更はインストールをそのまま実行するとエラーメッセージとして表示されます。あらかじめ変更しておきましょう。

Storybook のインストール
インストールの手順としては、Next.js の場合は公式サイトの React の手順で進めていきます。
以下のコマンドでインストールを進めます。
インストーラーが新しくインストールを実行するのかの確認を表示します。

しばらくすると、Storybook の画面が表示されます。

インストールが完了したターミナルの画面は以下の通りです。

ファイルの確認
Next.js に Storybook を追加した際の変更点を確認していきます。Visual Studio Code で変更点を見ると以下のようになります。

変更点だけをピックアップすると以下のようになります。
- .storybook — - storybook layout files
- package.json — - install storybook package
- vitest.config.ts — - config for Vitest
- vitest.shms.d.ts — - global type definitions for Vitest
インストール後の動作確認で npm run build を実行すると以下のようなエラーが表示されます。

これは、src/stories/Page.tsx のファイルの 43 行目で "args" という記述があり、これが ESlint でエラーになっています。以下のように書き換えてください。
これで build の実行が可能となりました。
Storybook の動作確認
現在のプロジェクトでは、コマンドを実行することで Next.js と Storybook が共存している形です。まず、Next.js を起動するときは以下のコマンドです。
これで Next.js が http://localhost:3000 で起動します。
また Storybook を起動するときは以下のコマンドで起動します。
これで Storybook が http://localhost:6006/ と Next.js とは別のポートで起動します。このため、同じプロジェクトで2つのプログラムが動くことがわかります。
なお、Storybook で作成したコンポーネントを build をして静的サイトとして展開することもできます。この場合は以下のコマンドで実行します。
以下のように build が実行されます。

そしてサイトは storybook-static に展開しています。

Tailwind CSS を利用する
Storybook を設定した段階では、Next.js で利用している Tailwind CSS を参照していない状態です。そこで、Tailwind CSS を参照する形に Storybook の設定を変更していきます。
スタイルシートの整理
スタイルシートのファイルを整理していきます。
- 既存のプロジェクトでは Next.js の初期の状態となるため、src/app/globals.css に Tailwind CSS で利用するファイルが適用されています。これを、src/styles/globals.css に移動します。
- src/stories のフォルダの中に含まれる css ファイルを上記と同様に src/styles に移動します
- 移動したスタイルシートを、globals.css の import で読み込むようにします。
styles のフォルダの中は以下のようになります。
- button.css
- globals.css
- header.css
- page.css
また、src/app/layout.tsx のファイルで読み込んでいるスタイルシートのパスも変更となるため、以下のように変更をします。
スタイルシートの設定としては、storybook が参照できるようにするために、以下のファイルもスタイルシートを読み込むように変更をします。
これで、スタイルシートの調整は完了しました。
components フォルダの作成
Next.js で利用するコンポーネントとして、storybook で用意しているコンポーネントを利用できるように、以下のように変更をします。
- src/stories/Configure.mdx と src/stories/assets を削除します
- src/stories のフォルダを src/components のフォルダに変更します。
- src/components/Button.tsx 、src/components/Header.tsx および src/components/Page.tsx で読み込んでいる css の行を削除します
続いて上記のコンポーネントを Storybook が認識できるように変更を進めます。まず、.storybook/main.ts において、今回作成をした components のフォルダの配下にファイルを配置しているように設定を変更します。
上記の変更で、Next.js で作成をするコンポーネントに対して、stories.ts のファイルを定義して、コンポーネントの表示ができるようになりました。
コンポーネントの更新
今回の Next.js のプロジェクトは App Router としているため、Button.tsx および Page.tsx はクライアント側での処理が追加されているため、以下の1行を追加する必要があります。
これで Next.js で利用できるコンポーネントになりました。
ただし、このコードを入れている場合 storybook で build を実行するとエラーが表示されます。以下のような画面が表示される形です。

前半の警告はまさに use client を追加したところが問題となっています。また後半の警告はサイズが大きくなっていることを示しています。
これを回避するために、.storybook/main.ts のファイルに以下のコードを追加します。
これで警告が表示されない形となりました。
Storybook のファイル構成
最後に Storybook で定義している stories.tsx ファイルの役割を紹介します。まず、 Button.tsx のための定義ファイル src/components/Button.stories.ts を上から順に機能を紹介していきます。
上記のコードは、同じフォルダにある Button.tsx に対する stories.ts になっていることを定義しています。
これは Storybook の画面において表示される内容の定義になります。
- Example グループの Button として表示
- レイアウトで中央に表示
- autodocs を利用して、自動的に Doc ファイルを作成
- argTypes でコンポーネントで利用する変数の定義
- onClick の実装
コンポーネントで利用するデータの定義を設定する際には、argTypes の項目を増やすことで対応が可能です。最後の以下の項目で、表示をする場合の値を設定して、サンプルを表示できるようにしています。
ダークモードの追加
Storybook を利用することで、ライトモード、ダークモードの切り替えを画面上で変更可能となります。これを活用すると、コンポーネントの作成、確認の作業が非常にやりやすくなります。
Storybook の設定
まずは Storybook 側の設定を進めていきます。
続いて Storybook の設定ファイルにインストールをした Addon を追加します。
Storybook が表示する際に、Next.js と同じように Class を指定してモードの切り替えをするように、withThemeByClassName の関連コードを追加します。
Tailwind CSS の設定
この設定は簡単で、globals.css ファイルに以下の行を追加するだけでダークモードが動作するようになります。
Card コンポーネントを追加する
ダークモードに対応した Card コンポーネントを作成していきます。まず、Card コンポーネントを以下のように作成します。
Card コンポーネントでは画像をアセットとして利用したいため、先にアセットの Interface を追加します。
この Asset の定義を利用して、Card で扱うデータ項目を設定します。今回、Card の画像の位置に関しては top と left を用意しました。
このカードのスタイルシートを以下のように作成しています。
また Storybook のプレビューで確認するときにダークモードが有効になるように、以下のスタイルシートも作成をします。
両方のファイルを globals.css で読み込んでください。今回はサンプルのスタイルも削除しました。
最後に、コンポーネントのサンプルを表示するファイルを以下のように作成をします。
なお、public に画像をコピーして、その画像ファイルを参照するように実装しています。
動作確認
それでは実際の動作確認を進めます。以下のコマンドを実行します。
Storybook が起動すると、今回追加をしたボタンが左側のメニューに追加されています。選択をすると以下のような画面になります。

モードの切替ボタンをクリックして、ダークモードにします。

意図した形でダークモードでの色が設定できています。続いて、画像の位置を左側にした場合の動作を確認すると、以下のような形で左側の時の表示も確認できました。

これでダークモードでの動作、そして表示に関するテストができました。
Vercel に展開する
今回作成をした Storybook のデータをいつでもサイトで参照できるように、Vercel に展開していきます。
- Vercel で New Project を開く
- 該当するリポジトリを指定する
- Framework Preset を Storybook を選択する

環境変数などはないため、追加の設定なしに展開をすることが可能です。しばらくすると、以下のように参照できるようになりました。

まとめ
今回は Next.js App Router に対して Storybook をインストール、そして Tailwind CSS を共有するところまで進めていきました。今回実施したサンプルのコードは以下のリポジトリ、およびデモサイトを参照できるようにしてあります。
- GitHub Repository - https://github.com/haramizu/nextjs-storybook
- Demo site - https://haramizu-nextjs-storybook-demo.vercel.app/