Storybookで自分用のUIカタログを作り、個人開発のUIを標準化する
はじめに
自分が、趣味でReactを使ったWebアプリを個人開発していると、セレクトボックスやフォーム項目など、毎回のように似たUIコンポーネントを作ることがありました。
アプリごとに実装していると、似たようなコンポーネントが増えたり、細かい仕様やスタイルにばらつきが出たりします。
そこで、個人開発で繰り返し作っていたUIコンポーネントを整理し、自分用のUIコンポーネントカタログを作成しました。
Storybookを使って、各コンポーネントの表示・動作・バリエーションを確認できるようにしています。
作ったもの
- 公開カタログ: https://noemaru1011.github.io/my-ui-catalog/
- GitHubリポジトリ: https://github.com/noemaru1011/my-ui-catalog
ReactとTypeScriptで構成したUIコンポーネントカタログです。
Storybook上でコンポーネントを個別に表示し、Propsによる表示の違いや、操作時の挙動などを確認できます。
主な目的は、個人開発で繰り返し実装していたUIを再利用可能な形に整理し、アプリ間で一貫性を保ちやすくすることです。
技術スタック
| 分類 | 技術 |
|---|---|
| Framework | React 19 |
| Language | TypeScript |
| UI Catalog | Storybook |
| Build Tool | Vite |
| Styling | Tailwind CSS 4 |
| UI Primitives | shadcn/ui |
| Form | React Hook Form、Zod |
| Linter / Formatter | Biome |
| Test | Vitest、Testing Library |
| Package Manager | npm |
| CI/CD | GitHub Actions |
| Deploy | GitHub Pages |
| AI | Codex |
コンポーネントの分類
コンポーネントは用途に応じて、いくつかのディレクトリに分けています。
Elements
アプリケーションのUIを構成する、再利用可能なコンポーネントを配置しています。
個人開発で何度も実装していたUIを、ここに集約していきます。
Layouts
コンポーネントの配置やレイアウトを制御するためのコンポーネントです。
現在は、以下のコンポーネントを用意しています。
CenterClusterContainerStack
UIそのものだけでなく、配置方法も共通化することで、レイアウトの実装をシンプルにすることを狙っています。
UI Primitives
src/components/ui/では、shadcn/uiをベースにした基本的なUI要素を管理しています。
ボタン、入力欄、ラベル、ポップオーバーなど、上位のコンポーネントを構成するための要素を配置しています。
なお、ボタンなどはshadcn/uiのコンポーネントをそのまま利用することが多いため、必要以上に独自コンポーネント化しない方針です。
Examples
複数のコンポーネントを組み合わせた使用例を管理しています。
個々のコンポーネントだけでなく、組み合わせたときの表示や使い方も確認できるようにしています。
特にRHF(controllerコンポーネントの使い方)やzodのとの連携をまとめました。
あえて共通化していないもの
すべてのUIを共通コンポーネントにするわけではありません。
例えば、テーブルやヘッダーなどはアプリごとに構成や要件が異なるため、現時点では共通コンポーネント化していません。
また、shadcn/uiで提供されているボタンなどの基本要素も、そのまま使うことが多いです。
共通化すること自体を目的にするのではなく、複数のアプリで再利用する可能性が高いものを中心に共通化する方針にしています。
Storybookで表示やバリエーションを確認する
各コンポーネントには、実装ファイルに加えてStoryとテストを配置しています。
例えば、セレクトボックスの場合は次のような構成です。
src/components/elements/Select/
├── Select.tsx
├── Select.test.tsx
└── Select.stories.tsx
Storyでは、基本表示だけでなく、Propsによる表示の違いや状態のバリエーションなどを確認できるようにしています。
コンポーネントの仕様を変更した場合も、対応するStoryを更新することで、変更後の表示や動作を確認しやすくしています。
これにより、個々のコンポーネントをアプリ全体から切り離して確認でき、実装時にも仕様を把握しやすくなります。
テスト方針
コンポーネントのテストには、VitestとReact Testing Libraryを使用しています。
実装の内部構造ではなく、利用者から観測できる振る舞いを中心にテストする方針です。
主な確認項目は次のとおりです。
- 初期表示: 初期表示やデフォルト状態が正しいこと
- Props: 指定値に応じて表示や動作が変化すること
- ユーザー操作: クリックや入力などに応じて期待する動作をすること
- 状態の変化: 操作後に表示や状態が適切に更新されること
-
制約条件:
disabledなどの制約が機能すること - アクセシビリティ: ロール、ラベル、ARIA属性などが適切に設定されていること
必要に応じてuserEventでユーザー操作を再現し、コンポーネントの仕様に合わせてテストを作成しています。
また、テスト方針や作成手順はSkillsとして整理し、コンポーネント間で一貫したテストを実施できるようにしています。
コンポーネントの仕様を追加・変更した場合は、関連するテストも作成・更新し、既存の動作への影響がないことを確認します。
開発環境とデプロイ
ローカルでの起動
Node.jsのバージョンを合わせたうえで、依存パッケージをインストールします。
nvm use
npm ci
続いて、Storybookを起動します。
npm run storybook
起動後、ブラウザで以下のURLにアクセスすると、コンポーネントカタログを確認できます。
Storybookのビルド
静的ビルドは、次のコマンドで実行します。
npm run build-storybook
ビルド成果物はstorybook-static/に出力されます。
CI/CD
GitHub Actionsを使ってCI/CDを構成しています。
- CI: コードのチェックやテストを実行
-
CD:
mainブランチへのpushをトリガーにStorybookをビルドし、GitHub Pagesへデプロイ
手動実行にも対応しています。
これにより、ローカル環境だけでなく、ブラウザからコンポーネントカタログを確認できるようにしています。
おわりに
今回、個人開発で繰り返し作っていたUIコンポーネントを整理し、Storybookを使ったカタログとしてまとめました。
すべてを共通化するとかえって扱いにくくなることもあるため、再利用性とアプリごとの柔軟性のバランスを意識しています。
今後も個人開発で必要になったコンポーネントを追加しながら、自分にとって使いやすいUIカタログに育てていきたいと思います。
実際のカタログとソースコードは以下から確認できます。
- UI Catalog: https://noemaru1011.github.io/my-ui-catalog/
- GitHub: https://github.com/noemaru1011/my-ui-catalog