1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

t3-appとcvaとstorybookを使ってみる

Posted at

やってみた理由

Next.js Conf 2022でもお話があったり
t3-appのドキュメントでも紹介されたので手を出してみようかなと。

ただ、cvaをインストールしても、コンポーネントの確認が必要になってくるので、
この機会にstorybookもインストールします(今まで触ったことがない)

手順

  1. t3-appの作成
    defaultフラグをつけて、tailwindcss,next-auth,prisma,trpcを全てインストールする(つけなかったら、何をインストールするか聞かれる)

    yarn create t3-app --default <app_name>
    
  2. class-variance-authorityをインストール

    yarn add class-variance-authority
    
  3. class-variance-authorityが使えるか確認してみる

    1. Buttonコンポーネントの作成(READMEからREADMEから取ってきた奴)

      ./src/components/button.tsx
      import React from "react";
      import { cva, type VariantProps } from "class-variance-authority";
      
      // ⚠️ Disclaimer: Use of Tailwind CSS is optional
      const button = cva(["font-semibold", "border", "rounded"], {
        variants: {
          intent: {
            primary: [
              "bg-blue-500",
              "text-white",
              "border-transparent",
              "hover:bg-blue-600",
            ],
            // **or**
            // primary: "bg-blue-500 text-white border-transparent hover:bg-blue-600",
            secondary: [
              "bg-white",
              "text-gray-800",
              "border-gray-400",
              "hover:bg-gray-100",
            ],
          },
          size: {
            small: ["text-sm", "py-1", "px-2"],
            medium: ["text-base", "py-2", "px-4"],
          },
        },
        compoundVariants: [
          {
            intent: "primary",
            size: "medium",
            class: "uppercase",
            // **or** if you're a React.js user, `className` may feel more consistent:
            // className: "uppercase"
          },
        ],
        defaultVariants: {
          intent: "primary",
          size: "medium",
        },
      });
      
      export interface ButtonProps
        extends React.ButtonHTMLAttributes<HTMLButtonElement>,
          VariantProps<typeof button> {}
      
      export const Button: React.FC<ButtonProps> = ({
        className,
        intent,
        size,
        ...props
      }) => <button className={button({ intent, size, className })} {...props} />;
      

      pagesディレクトリで適当にコンポーネントを呼び出す

      ./src/pages/test.tsx
      import { Button } from "../components/button";
      
      const Page = () => {
        return (
          <section>
            <div><Button intent={"primary"}>Test</Button></div>
            <div><Button intent={"secondary"}>Test</Button></div>
          </section>
        );
      };
      
      export default Page;
      
    2. Next.jsを起動させて作成したtestページにアクセスしてみる
      http://localhost:3000/test

      yarn dev
      

      こんな感じで表示されます。
      作ったコンポーネントをいちいちNext.jsのページに作成して確認したくないので、
      storybookをインストールしましょう
      スクリーンショット 2023-01-15 1.12.17.png

  4. storybookのインストール

    yarn dlx storybook init
    

    eslint使ってるか聞かれると思うので、y/nで答えて終了を待つ
    (デフォルトではインストールされてないのでn)

    initコマンドで、package.jsonの書き込みや、./.storybook/,./src/stories/が作成される

  5. storybookの起動

    yarn run storybook
    

    こんな感じで初期画面で表示されるので、
    自分が作成したボタンも表示させてみる
    スクリーンショット 2023-01-15 1.21.03.png

  6. storyを作成する

    ./src/components/Button.stories.tsx
    import { ComponentStory, ComponentMeta } from "@storybook/react";
    import { Button } from "./button";
    
    export default {
      title: "Example/custom-button",
      component: Button,
      argTypes: {},
    } as ComponentMeta<typeof Button>;
    
    const Template: ComponentStory<typeof Button> = (args) => (
      <Button {...args}>Button</Button>
    );
    
    export const Primary = Template.bind({});
    Primary.args = {
      intent: "primary",
      size: "medium",
    };
    
    export const Secondary = Template.bind({});
    Secondary.args = {
      intent: "secondary",
    };
    

    もう一度storybookを確認する(hotreloadされてるのでコマンド終了してしまった人は再度起動して確認)
    スクリーンショット 2023-01-15 1.25.23.png

    普通のボタンだ...
    Chromeの検証で確認するとclassは反映されているので、
    CSSが読み込まれてないことに気づく...
    スクリーンショット 2023-01-15 1.27.18.png

    postcss用のアドオンをインストール

    yarn add --dev @storybook/addon-postcss
    

    設定ファイルを編集

    ./.storybook/main.js
    module.exports = {
      stories: ["../src/**/*.stories.mdx", "../src/**/*.stories.@(js|jsx|ts|tsx)"],
      addons: [
        "@storybook/addon-links",
        "@storybook/addon-essentials",
        "@storybook/addon-interactions",
    +     {
    +       name: "@storybook/addon-postcss",
    +       options: {
    +         postcssLoaderOptions: {
    +           implementation: require("postcss"),
    +         },
    +       },
    +     },
      ],
      framework: "@storybook/react",
      core: {
        builder: "@storybook/builder-webpack5",
      },
    };
    
    
    ./.storybook/preview.js
    + import "../src/styles/globals.css";
    
    export const parameters = {
      actions: { argTypesRegex: "^on[A-Z].*" },
      controls: {
        matchers: {
          color: /(background|color)$/i,
          date: /Date$/,
        },
      },
    }
    

    この状態でstorybookを確認すると,,,

    無事cssが適応されてますね
    スクリーンショット 2023-01-15 1.33.40.png

  7. 最後に不要なファイルや設定を削除する(必要な人は)
    デフォルトのstoriesフォルダを削除

    rm -rf ./src/stories/
    

    storiesフォルダをもっと明確に指定

    ./.storybook/main.js
    module.exports = {
    +   stories: ["../src/components/**/*.stories.@(js|jsx|ts|tsx)"],
      addons: [
        "@storybook/addon-links",
        "@storybook/addon-essentials",
        "@storybook/addon-interactions",
        {
          name: "@storybook/addon-postcss",
          options: {
            postcssLoaderOptions: {
              implementation: require("postcss"),
            },
          },
        },
      ],
      framework: "@storybook/react",
      core: {
        builder: "@storybook/builder-webpack5",
      },
    };
    

まとめ

以上、t3-appのプロジェクトにclass-variance-authorityとstorybookを入れる流れでした。
storybookには触れたことがなかったんですが、
class-variance-authorityでよりtailwindcssが使いやすくなりそうだったので導入してみました。
記事では述べていませんが、headlessuiと組み合わせることでより効果を発揮してくれそうです。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?