24
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

tailwind-variantsを触ってみた

Posted at

1. はじめに

今回は個人開発でTailwind Variantsを触ったので忘れないようにアウトプットします!
TailwindCSS初学者の方や、Tailwind Variantsを触ったことがない方に参考になれば幸いです!

2. Tailwind Variantsとは?

概要

Tailwind Variantsは、Tailwind CSSのユーティリティクラスを組み合わせて再利用可能なコンポーネントやバリエーションを作成できるもののようです。

メリット

TailwindCSSだけで書くと背景色だけ変えたい時に条件式を書いたり複数コンポーネントを作成していたところを、Tailwind Variantsを使うことで、1つのコンポーネントで複数のバリエーションを作成することができるので可読性やコンポーネントがめちゃ増えるみたいなことがなくなるので保守性も良くなるのでは!と思ってます。

3. Tailwind Variantsの基本的な使い方

インストール方法

Tailwind Variantsの導入手順(npmまたはyarnでのインストール)。

npm install tailwind-variants

variantsを使用したシンプルな例

  • baseで全てに適応される基本のスタイルを設定できる
  • variantsの中に自分の好きな名前でバリエーションを設定できる(今回は文字サイズと色を指定したいので、sizeとcolorで指定)
  • defaultVariantsには何も指定しなかった場合にあたるスタイルを設定できる
import { tv } from 'tailwind-variants';

const button = tv({
  base: 'px-4 py-2 rounded',
  variants: {
    size: {
      small: "text-sm p-2",
      base: "text-base p-4",
      large: "text-lg p-6",
    },
    color: {
      primary: "bg-blue-500 hover:bg-blue-700",
      secondary: "bg-red-500 hover:bg-red-700",
      success: "bg-green-500 hover:bg-green-700"
    },
  },
  defaultVariants: {
    size: 'large',
    color: 'primary',
  },
});


// 別ファイルでButtonコンポーネントを呼び出してcolorとかsizeをpropsで渡す
import { Button } from "./conponents/Button";

// 色をそれぞれつけてあるので上からprimary(赤), secondary(青), success(緑)に設定した色が当たる
<div className="flex gap-5 flex-col">
    <h2 className="font-bold text-lg">色だけつけたやつ</h2>
    <Button>base</Button>
    <Button color="secondary">secondary</Button>
    <Button color="success">success</Button>
</div>

// size="large"を指定しているのでtext-lgが適応される
<div className="flex gap-5 flex-col">
    <h2 className="font-bold text-lg">sizeがlgのやつ</h2>
    <Button size="large">base-disable</Button>
    <Button size="large" color="secondary">
        secondary
    </Button>
    <Button size="large" color="success">
        success
    </Button>
</div>

disableの時のスタイルも簡単に作成可能

import { tv } from 'tailwind-variants';

const button = tv({
  base: 'px-4 py-2 rounded',
  variants: {
    size: {
      small: "text-sm p-2",
      base: "text-base p-4",
      large: "text-lg p-6",
    },
    color: {
      primary: "bg-blue-500 hover:bg-blue-700",
      secondary: "bg-red-500 hover:bg-red-700",
      success: "bg-green-500 hover:bg-green-700"
    },
    disable: {
      true: "pointer-events-none opacity-20",
    },
  },
  defaultVariants: {
    size: 'large',
    color: 'primary',
  },
});

// 別ファイルでButtonコンポーネントを呼び出してcolorとかsizeをpropsで渡す
import { Button } from "./conponents/Button";

// disableがtrueになっているのdisable時のスタイルが当たる
<div className="flex gap-5 flex-col">
    <h2 className="font-bold text-lg">disableがtrueのやつ</h2>
    <Button disable={true}>base-disable</Button>
    <Button color="secondary" disable={true}>
        secondary
    </Button>
    <Button color="success" disable={true}>
        success
    </Button>
</div>

↓↓↓ 今のところこんな感じ ↓↓↓

image.png

slotsを使った複数の要素のスタイルを同時に変更するやり方

今回は、入力フォームのlabelやinputにそれぞれスタイルを適用し、エラーが発生した際に基本の色が赤色に変わるようにする実装を、slotsを使用して試してみました。

import React from "react";
import { tv } from "tailwind-variants";

const inputField = tv({
  slots: {
    label: "mb-2 block text-sm font-medium text-gray-900 dark:text-white",
    input:
      "block w-full rounded-lg border border-gray-300 bg-gray-50 p-2.5 text-sm text-black",
    error: "mt-2 text-sm text-red-600 dark:text-red-500",
  },
  variants: {
    size: {
      lg: {
        label: "text-lg",
        input: "text-lg",
      },
      default: {},
    },
    error: {
      true: {
        label: "text-red-700 dark:text-red-500",
        input:
          "border-red-500 bg-red-50 text-red-900 placeholder-red-700 focus:border-red-500 focus:ring-red-500",
      },
      false: {},
    },
  },
  defaultVariants: {
    size: "default",
    error: false,
  },
});

interface inputProps {
  label: string;
  error?: boolean;
  errorMessage?: string;
  size?: "lg" | "default";
  placeholder?: string;
}

export const Input: React.FC<inputProps> = ({
  label,
  errorMessage,
  error,
  size,
}) => {
  const {
    label: labelClass,
    error: errorClass,
    input: inputClass,
  } = inputField();

  return (
    <div>
      <label className={labelClass({ error, size })}>{label}</label>
      <input type="text" className={inputClass({ error, size })} />
      {errorMessage && <div className={errorClass()}>{errorMessage}</div>}
    </div>
  );
};

//他のページで呼び出すとき
import { Input } from "./conponents/Input";

<div className="flex gap-5 flex-col">
 <Input
     label="エラーがあった時"
     errorMessage="エラーです"
     error={true}
  />
 <Input label="エラーがない+サイズをlgにした場合" size="lg" />
</div>

image.png

7. まとめ

Tailwind Variants・slotsの基本的な使い方をまとめてみました!
Tailwind Variantsには、Compound variantsやレスポンシブ対応など、まだ多くの機能がありますので、気になる方は公式ドキュメントをぜひみてみてください!

8. 参考資料

24
10
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
24
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?