みなさん、こんにちは! 山田です。
前回の記事で Figma を使ってボタンコンポーネントを作ってみました。
今回はそのデザインを元に React と Tailwind CSS で実装していきたいと思います。
開発環境の準備
今回開発環境に Nextjs を選びました。
Next.js はセットアップ時に Tailwind CSS のインストールを選択できるので、すぐに開発を始められます。
セットアップ時の質問は全てデフォルトで進めていきます。
> npx create-next-app@latest
Need to install the following packages:
create-next-app@14.0.4
Ok to proceed? (y) y
✔ What is your project named? … button-ui-example
✔ Would you like to use TypeScript? … No / Yes # Yesを選択
✔ Would you like to use ESLint? … No / Yes # Yesを選択
✔ Would you like to use Tailwind CSS? … No / Yes # Yesを選択
✔ Would you like to use `src/` directory? … No / Yes # Noを選択
✔ Would you like to use App Router? (recommended) … No / Yes # Yesを選択
✔ Would you like to customize the default import alias (@/*)? … No / Yes # Noを選択
Next.js のセットアップが完了したら、プロジェクトのディレクトリに移動しておきます。
UI の確認は Storybook で行うので、こちらもセットアップします。
npx storybook@latest init
セットアップが完了すると、自動的に Storybook が起動します。
プリセットでいくつかコンポーネントが用意されていますが、不要なので削除しておきます。
rm -rf stories/*
Storybook の設定
次に Storybook の設定を行います。
簡単なボタンコンポーネントのファイルを作成し、以下の内容で保存します。
// app/components/Button.tsx
import { ReactNode, FC } from "react";
type Props = {
children: ReactNode;
};
export const Button: FC<Props> = ({ children }) => {
return <button>{children}</button>;
};
次に、このコンポーネントを Storybook で確認できるようにします。
// stories/Button.stories.tsx
import type { Meta, StoryObj } from "@storybook/react";
import { Button } from "../app/components/Button";
const meta = {
component: Button,
parameters: {
layout: "centered",
},
tags: ["autodocs"],
} satisfies Meta<typeof Button>;
export default meta;
type Story = StoryObj<typeof meta>;
export const Primary: Story = {
args: {
children: "ボタン",
},
};
Storybook を確認すると、ボタンコンポーネントが表示されます。
meta オブジェクトの tags に autodocs
を指定することで、コンポーネントのドキュメントを自動生成することができます。
また、parameters に layout: "centered"
を指定することで、コンポーネントを中央に表示することができるので覚えておくと便利です。
最後に preview.js に globals.css を読み込ませます。
この時 globals.css に記載されている@tailwind xxxx
以外の内容は不要なので削除しておきます。
// .storybook/preview.js
import type { Preview } from "@storybook/react";
import "../app/globals.css";
(省略)
これで Tailwind CSS によるスタイルが Storybook に反映されるようになりました。
ボタンコンポーネントの実装
Figma でデザインしたボタンコンポーネントにはいくつかのバリアントがありました。
ボタンコンポーネントに渡すプロパティの値によってバリアントを変化させるのが一般的かと思いますが、プロパティの数が多くなってくると、条件分岐を独自に実装するのはかなり面倒です。
そこで、「Class Variance Authority」というライブラリを使って、複数のバリアントを持つコンポーネントを簡単に実装できるようにします。
まずはライブラリをインストールします。
npm install class-variance-authority
次に、Button コンポーネントを以下のように修正します。
// app/components/Button.tsx
import { cva, type VariantProps } from "class-variance-authority";
import { ButtonHTMLAttributes, FC } from "react";
const button = cva("text-white rounded-md", {
variants: {
intent: {
primary: "bg-blue-500 hover:bg-blue-600",
secondary: "bg-pink-500 hover:bg-pink-600",
},
size: {
sm: "px-2 py-1 text-sm",
md: "px-4 py-2 text-base",
lg: "px-6 py-3 text-lg",
},
},
defaultVariants: {
intent: "primary",
size: "md",
},
});
export interface ButtonProps
extends ButtonHTMLAttributes<HTMLButtonElement>,
VariantProps<typeof button> {}
export const Button: FC<ButtonProps> = ({
className,
intent,
size,
children,
...props
}) => {
return (
<button className={button({ intent, size, className })} {...props}>
{children}
</button>
);
};