next.js+tailwindでstorybookを動作する方法

nextjsでフロントエンドの開発をする際,tailwindのcssスタイルがstorybookに反映されなかったので,設定方法を自分なりにまとめた.使用している環境はWSL2です.


# nextjsでcreate-new-app


```
npx create-next-app@latest
```
ここでこれから作るアプリケーションの初期設定を聞かれる.
```
✔ What is your project named? … test
✔ Would you like to use TypeScript? … No / Yes
✔ Would you like to use ESLint? … No / Yes
✔ Would you like to use Tailwind CSS? … No / Yes
✔ Would you like to use `src/` directory? … No / Yes
✔ Would you like to use App Router? (recommended) … No / Yes
✔ Would you like to customize the default import alias (@/*)? … No / Yes
```
今回は初期設定の四行目のTailwindをYesにした場合のstorybook周りの設定について説明する.(すべてyesにしている)


## storybookの設定
まずはstorybookが正しく起動するか確認するため,appフォルダの直下にTest.tsxを配置しよう.

```Login.tsx
import React, { useState } from 'react';

const Login: React.FC = () => {
  const [email, setEmail] = useState('');
  const [password, setPassword] = useState('');

  const handleSubmit = (event: React.FormEvent) => {
    event.preventDefault();
    // ログイン処理をここに追加
    console.log('Email:', email);
    console.log('Password:', password);
  };

  return (
    <div className="flex items-center justify-center min-h-screen bg-gray-100">
      <div className="w-full max-w-md bg-white p-8 rounded-lg shadow-md">
        <h2 className="text-2xl font-bold text-center mb-6">ログイン</h2>
        <form onSubmit={handleSubmit}>
          <div className="mb-4">
            <label htmlFor="email" className="block text-gray-700 font-bold mb-2">
              メールアドレス
            </label>
            <input
              type="email"
              id="email"
              value={email}
              onChange={(e) => setEmail(e.target.value)}
              className="w-full px-3 py-2 border rounded-lg shadow-sm focus:outline-none focus:ring focus:border-blue-300"
              placeholder="example@example.com"
              required
            />
          </div>
          <div className="mb-6">
            <label htmlFor="password" className="block text-gray-700 font-bold mb-2">
              パスワード
            </label>
            <input
              type="password"
              id="password"
              value={password}
              onChange={(e) => setPassword(e.target.value)}
              className="w-full px-3 py-2 border rounded-lg shadow-sm focus:outline-none focus:ring focus:border-blue-300"
              placeholder="********"
              required
            />
          </div>
          <div className="flex items-center justify-between">
            <button
              type="submit"
              className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded focus:outline-none focus:shadow-outline"
            >
              ログイン
            </button>
            <a href="#" className="inline-block align-baseline font-bold text-sm text-blue-500 hover:text-blue-800">
              パスワードを忘れましたか?
            </a>
          </div>
        </form>
      </div>
    </div>
  );
};

export default Login;
```

どんなファイルでもよいのだが,今回はログイン画面のファイルとした.さらにstorybookでこのコンポーネントを確認するための,storeisファイルも同じ階層に配置する.

```Login.stories.tsx
import React from 'react';
import { Meta, Story } from '@storybook/react';
import Login from './Login';

export default {
  title: 'Pages/Login',
  component: Login,
} as Meta;

const Template: Story = (args) => <Login {...args} />;

export const Default = Template.bind({});
Default.args = {};

```

試しにこの状態でstorybookを起動させよう.下記のstorybookをインストールするコードはprojectの階層で行うことに注意.

```bash
npx sb init
```

storybookのフォルダが作成され,2,3分のダウウンロードが終わるとブラウザ上でstorybookが起動されるはずである.

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3787219/cc71fe1e-98eb-322b-1ea4-153978399469.png)

しかし,tailwindのスタイルが適応されていない状態である.

## tailwindの設定
いくつか設定を変えていく.まずはstorybookフォルダのpreview.tsを変更する
```preview.ts
import type { Preview } from "@storybook/react";
import '../src/app/globals.css'; //この部分を追加
const preview: Preview = {
  parameters: {
    controls: {
      matchers: {
        color: /(background|color)$/i,
        date: /Date$/i,
      },
    },
  },
};

export default preview;
```
globals.cssを読み込まないとstorybookに反映されない.globals.cssのフォルダパスはsrcを作っているか否かで変わるので,お手元のパスに従いましょう.

続いてプロジェクト最上位階層にある`postcss.config.mjs`の名前を`postcss.config.js`に変更.

そしてターミナル上で下記のコマンドでautoprefixerをインストールする.
```
npm install autoprefixer

```
インストールしたautoprefixerを有効にするためファイルの内容を変更
```postcss.config.js
module.exports = {
  plugins: {
    tailwindcss: {},
    autoprefixer: {},  // autoprefixerを有効にする設定
  },
};

```

## 実行結果
以上の設定を踏まえて再度`npx sb init`を実行すると以下のようになる.
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3787219/41a69b3c-a643-b834-8d0a-f26666901c17.png)

tailwindが反映されていることがわかる.