📚
Bun+ReactプロジェクトにStorybookを導入する
はじめに
Bunは非常に動作が早いNode.js互換のJavaScriptランタイムになります。今回はBunを使いつつ、フロントエンド開発では絶対に欠かせない、コンポーネントカタログ生成ツールのStorybookを導入します。
この記事では、Bun + Vite + Reactの環境にStorybookを導入する方法を書きます。
bunx run storybook --init
では環境がセットアップが出来なかったので、手動で用意する方法を紹介します。
プロジェクトを生成
以下のコマンドで新しいプロジェクトを生成します。
bun create vite my-app
frameworkはReact
、variantはTypeScript + SWC
を選択します。
各種設定ファイルの変更
package.jsonを修正する
以下の内容を追加します。
package.json
{
...
"scripts": {
"sb": "storybook dev -p 6006",
"sb:build": "storybook build"
},
"devDependencies": {
"storybook": "^8.0.9",
"@chromatic-com/storybook": "^1.3.1",
"@storybook/addon-essentials": "^8.0.6",
"@storybook/addon-interactions": "^8.0.6",
"@storybook/addon-links": "^8.0.6",
"@storybook/addon-onboarding": "^8.0.6",
"@storybook/blocks": "^8.0.6",
"@storybook/react": "^8.0.6",
"@storybook/react-vite": "^8.0.6",
"@storybook/test": "^8.0.6",
}
}
Storybookの設定ファイルを追加する
.storybook/main.ts
import type { StorybookConfig } from "@storybook/react-vite";
const config: StorybookConfig = {
stories: ["../src/**/*.mdx", "../src/**/*.stories.@(js|jsx|mjs|ts|tsx)"],
addons: [
"@storybook/addon-onboarding",
"@storybook/addon-links",
"@storybook/addon-essentials",
"@chromatic-com/storybook",
"@storybook/addon-interactions",
],
framework: {
name: "@storybook/react-vite",
options: {},
},
docs: {
autodocs: "tag",
},
};
export default config;
.storybook/preview.tsx
import type { Preview } from "@storybook/react";
import React from "react";
import "../src/index.css";
const preview: Preview = {
parameters: {
controls: {
matchers: {
color: /(background|color)$/i,
date: /Date$/i,
},
},
},
decorators: [(Story) => <Story />],
};
export default preview;
サンプルのコンポーネントとストーリーを追加
サンプルコンポーネントを追加する
src/sampleButton/index.tsx
import "./index.css";
interface ButtonProps {
/**
* Is this the principal call to action on the page?
*/
primary?: boolean;
/**
* What background color to use
*/
backgroundColor?: string;
/**
* How large should the button be?
*/
size?: "small" | "medium" | "large";
/**
* Button contents
*/
label: string;
/**
* Optional click handler
*/
onClick?: () => void;
}
/**
* Primary UI component for user interaction
*/
export const Button = ({
primary = false,
size = "medium",
backgroundColor,
label,
...props
}: ButtonProps) => {
const mode = primary
? "storybook-button--primary"
: "storybook-button--secondary";
return (
<button
type="button"
className={["storybook-button", `storybook-button--${size}`, mode].join(
" "
)}
style={{ backgroundColor }}
{...props}
>
{label}
</button>
);
};
export default Button;
src/SampleButtn/index.css
.storybook-button {
font-family: "Nunito Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
font-weight: 700;
border: 0;
border-radius: 3em;
cursor: pointer;
display: inline-block;
line-height: 1;
}
.storybook-button--primary {
color: white;
background-color: #1ea7fd;
}
.storybook-button--secondary {
color: #333;
background-color: transparent;
box-shadow: rgba(0, 0, 0, 0.15) 0px 0px 0px 1px inset;
}
.storybook-button--small {
font-size: 12px;
padding: 10px 16px;
}
.storybook-button--medium {
font-size: 14px;
padding: 11px 20px;
}
.storybook-button--large {
font-size: 16px;
padding: 12px 24px;
}
ストーリーファイルを追加する
index.stories.tsx
import type { Meta, StoryObj } from "@storybook/react";
import { fn } from "@storybook/test";
import Button from ".";
// More on how to set up stories at: https://storybook.js.org/docs/writing-stories#default-export
const meta = {
title: "Example/Button",
component: Button,
parameters: {
// Optional parameter to center the component in the Canvas. More info: https://storybook.js.org/docs/configure/story-layout
layout: "centered",
},
// This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/writing-docs/autodocs
tags: ["autodocs"],
// More on argTypes: https://storybook.js.org/docs/api/argtypes
argTypes: {
backgroundColor: { control: "color" },
},
// Use `fn` to spy on the onClick arg, which will appear in the actions panel once invoked: https://storybook.js.org/docs/essentials/actions#action-args
args: { onClick: fn() },
} satisfies Meta<typeof Button>;
export default meta;
type Story = StoryObj<typeof meta>;
// More on writing stories with args: https://storybook.js.org/docs/writing-stories/args
export const Primary: Story = {
args: {
primary: true,
label: "Button",
},
};
export const Secondary: Story = {
args: {
label: "Button",
},
};
export const Large: Story = {
args: {
size: "large",
label: "Button",
},
};
export const Small: Story = {
args: {
size: "small",
label: "Button",
},
};
以上で設定完了です。
Storybookの起動
パッケージのインストール
bun i
起動コマンド
bun run sb
おわりに
BunでもStorybookを起動することができました😊
今後もBunを触っていきたいと思います。
Discussion