🎨Storybook@7入門:Next.js + TailwindCSSへのステップバイステップ組み込みガイド
Storybookのメジャーバージョンが7にアップデートしてからしばらく経ちます。
しかしながらNext.jsとtailwindCSSの組み合わせにStorybookを使用する記事が少なかったため、
組み込むために行ったことをまとめました。
動作確認環境は以下のとおりです。
"next": "13.3",
"react": "^18.2.0",
"tailwindcss": "^3.3.2",
"storybook": "^7.0.11",
"@storybook/addon-essentials": "^7.0.11",
"@storybook/addon-interactions": "^7.0.11",
"@storybook/addon-links": "^7.0.11",
"@storybook/blocks": "^7.0.11",
"@storybook/nextjs": "^7.0.11",
"@storybook/react": "^7.0.11",
"@storybook/testing-library": "^0.1.0",
"storybook-addon-pseudo-states": "^2.0.1",
インストール手順
公式の通りにイニシャライズします。
npx storybook@latest init
package.jsonに追加されるのを確認します。
(不足していたら別途インストールしてください)
"devDependencies": {
"@storybook/addon-essentials": "^7.0.11",
"@storybook/addon-interactions": "^7.0.11",
"@storybook/addon-links": "^7.0.11",
"@storybook/blocks": "^7.0.11",
"@storybook/nextjs": "^7.0.11",
"@storybook/react": "^7.0.11",
"@storybook/testing-library": "^0.1.0",
"eslint-plugin-storybook": "^0.6.12",
"storybook": "^7.0.11",
},
.eslintrc.jsonにも追記します。
"extends": [
"prettier",
"plugin:storybook/recommended"
],
Storybookはバージョンが7になったことで、6では手動で入れていたアドオンが集約されました。
tailwindを導入している場合は以下のように記述するだけでStorybook側に認識されます。
@import 'tailwindcss/base';
@import 'tailwindcss/components';
@import 'tailwindcss/utilities';
import type { Preview } from '@storybook/react';
import '../src/styles/tailwind.css';
const preview: Preview = {
parameters: {
actions: { argTypesRegex: '^on[A-Z].*' },
controls: {
matchers: {
color: /(background|color)$/i,
date: /Date$/,
},
},
},
};
export default preview;
import type { StorybookConfig } from '@storybook/nextjs';
const config: StorybookConfig = {
stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|ts|tsx)'],
addons: [
'@storybook/addon-links',
'@storybook/addon-essentials',
'@storybook/addon-interactions',
],
framework: {
name: '@storybook/nextjs',
options: {},
},
docs: {
autodocs: 'tag',
},
};
export default config;
各コンポーネントと対になるStorybookを追加する
例として、Buttonコンポーネントを取り上げます。
最終的な実装は以下のとおりです。
import React, { ButtonHTMLAttributes } from 'react';
import classNames from "classnames"
type ButtonProps = ButtonHTMLAttributes<HTMLButtonElement>;
export const Button: React.FC<ButtonProps> = ({ children, innerClassName, ...rest }) => {
return (
<button
className={classNames([innerClassName, "bg-custom-blue rounded-md bg-blue-500 px-4 py-2 text-white hover:bg-blue-600 focus:outline-none focus:ring-2 focus:ring-blue-500"])}
{...rest}
>
{children}
</button>
);
};
これと対になるStorybookファイルは以下のように実装しました。
import { Meta, StoryObj } from '@storybook/react';
import { Button } from './index';
const meta = {
title: 'MySite/Buttons(ボタン)',
component: Button,
tags: ['autodocs'],
argTypes: {
innerClassName: {
control: {
type: 'text',
},
},
},
} satisfies Meta<typeof Button>;
export default meta;
type Story = StoryObj<typeof Button>;
export const _Button: Story = {
render: (arg) => <Button {...arg}>Button</Button>,
};
Storybookの実装
この節では、細かい実装部分を取り上げます。
Storybook@7ではメタ情報をmeta
変数にまとめ、default exportするようになりました。
const meta = {
title: 'MySite/Buttons(ボタン)',
component: Button,
tags: ['autodocs'],
} satisfies Meta<typeof Button>;
export default meta;
このうち、title
プロパティに指定するのがStorybookに表示されるコンポーネントのグループ名になります。
「/」で区切ることでディレクトリのように階層構造を表現できます。
また、tags配列に挿入しているautodocs
は、公式ドキュメントによると、
const meta: Meta<typeof Button> = {
title: 'Button',
component: Button,
//👇 Enables auto-generated documentation for the component story
tags: ['autodocs'],
argTypes: {
backgroundColor: { control: 'color' },
},
};
とあるので、ブラウザで確認する際の自動生成のために必要であることがわかります。
ちなみに、export const _Button
とすると、
Storybook上のコンポーネント名はアンダースコアを取り除いた状態(_Button
の場合はButton
)で表示されます。
PropsをStorybook側から受け渡す
meta変数のargTypes
プロパティを追加し、propsinnerClassName
を登録し、Storybook上から入力できるようにします。
const meta = {
title: 'MySite/Buttons(ボタン)',
component: Button,
tags: ['autodocs'],
argTypes: {
innerClassName: {
control: {
type: 'text',
},
},
},
} satisfies Meta<typeof Button>;
また、同ファイル内で宣言している_Buttonオブジェクトにて、renderメソッドを介して引数を受け取ることが出来ます。
export const _Button: Story = {
render: (arg) => <Button {...arg}>Button</Button>,
};
Storybook上ではテキストを入力できるよう表示されるようになりました。
ロゴやサービス名を表示させる
Storybookをブラウザで表示させると、デフォルトではStorybookのロゴが表示されます。
このままでも問題ないですが、自社のロゴやサービス名を表示させることで、より自分たちのデザインシステムとして感じることができ、
気持ちの面でもよい効果をもたらしますので変更することをオススメします!
この機能は@storybook/addon-essentials
が受け持ちますが、これまでの手順の中ですでにインストールされています。
.storybook
ディレクトリ に manager.js
を追加し、以下のように記述することで変更することで実装できます。
import { addons } from '@storybook/addons';
import { create } from '@storybook/theming';
addons.setConfig({
theme: create({
base: 'light', // or 'dark'
brandTitle: 'My Service',
brandImage: '<IMAGE_PATH>'
}),
});
他にも設定することができる項目があるので、公式ドキュメントをご確認ください。
まとめ
Next.jsとtailwindCSSを利用したプロジェクトにStorybookの実装する方法を見てきました。
ぜひ取り入れてみてください!
ちょっと社では絶賛エンジニアを募集しています!
Jamstackに興味があるエンジニアさんはぜひご連絡ください〜〜
一緒に働きましょう〜〜🙌
ちょっと株式会社
ちょっと株式会社(chot-inc.com)のエンジニアブログです。 フロントエンドエンジニア募集中! カジュアル面接申し込みはこちらから chot-inc.com/recruit/iuj62owig
Discussion