📚

React✖️Tailwind CSSで一緒に使いたいライブラリ4選

2024/07/11に公開

ReactのスタイリングライブラリとしてTailwind CSSを使われる方は、そこそこいるのではないでしょうか?
そんな方にオススメのライブラリがあるので、紹介します。

✨ prettier-plugin-tailwindcss

https://github.com/tailwindlabs/prettier-plugin-tailwindcss

tailwindの欠点として、クラス名が長くなりやすいということがあります。この時、tailwindのユーティリティクラスの並びが不規則だとさらに読みにくくなります。クラス名を自動でソートしてくれるprettierのプラグインを公式が配布しています。それがprettier-plugin-tailwindcssです。公式サイトにも案内があります。

その案内にも例が挙げられていますが、このプラグインを使うと以下のように、prettierがクラス名の並び替えを行なってくれるようになります。

- <div class="text-gray-700 shadow-md p-3 border-gray-300 ml-4 h-24 flex border-2">
+ <div class="ml-4 flex h-24 border-2 border-gray-300 p-3 text-gray-700 shadow-md">
    <!-- ... -->
  </div>

🔀 tailwind-merge

https://github.com/dcastil/tailwind-merge

Reactユーザーは、tailwindでスタイリングされたコンポーネントに対して、微妙なスタイリングの調整のために、propsで追加のクラス名を受け取り、クラス名に追加するということをやりたい時があると思います。

const MyComponent: React.FC<{ className?: string }> = ({ className }) => {
  return (
    <SomeComponent
      className={`block w-full rounded-lg p-2.5 text-sm bg-blue-300 ${className || ""}`}
    />
  );
};

ただ、この実装ではクラス名の競合が考慮できていません。例えば、クラス名が"bg-blue-300 bg-red-300"となった時、実際に適用されるスタイルは、どちらでしょうか?答えは試してみないと分かりません。後に書いた方が優先されるなど考えた人がいるかも知れませんが、文字列内のクラスの順序は一切関係がありません。

そんな時に活躍するのが、tailwind-mergeです。このライブラリは、tailwindのクラス名の競合を解決し、後に書いたものが優先されるようになります。

以下は、公式のGithubより引用した実行例です。

import { twMerge } from 'tailwind-merge'

twMerge('px-2 py-1 bg-red hover:bg-dark-red', 'p-3 bg-[#B91C1C]')
// -> 'hover:bg-dark-red p-3 bg-[#B91C1C]'

また、clsxやclassnamesのようなクラス名の結合を行う関数twJoinも提供しています。

twJoin(
    'border border-red-500',
    hasBackground && 'bg-red-100',
    hasLargeText && 'text-lg',
    hasLargeSpacing && ['p-2', hasLargeText ? 'leading-8' : 'leading-7'],
)
// hasBackground = true, hasLargeSpacing = trueの場合
// -> "border border-red-500 bg-red-100 p-2"
使用例

私は、以下のようなtailwindのクラス名の結合と競合の解決を行う関数cnを定義し、使い回しています。

import { ClassNameValue, extendTailwindMerge, twJoin } from "tailwind-merge";

const twMerge = extendTailwindMerge({
  extend: {
    // tailwind.config.jsで拡張したものを記述する
    theme: {
      colors: [
        {
          primary: ["light", "DEFAULT", "dark"],
          accent: ["light", "DEFAULT", "dark"],
        },
      ],
    },
  },
});

export const cn = (...classLists: ClassNameValue[]) => {
  return twMerge(twJoin(...classLists));
};

🧩 HeadlessUI

https://headlessui.com/

Headless UIは、コンポーネントライブラリです。Reactのコンポーネントライブラリは、MUIAnt Designなど、高機能なものがさまざまありますが、このようなライブラリにTailwindでスタイリングしようとすると思うようにならないことが多いです。そもそもスタイルが適用されない場合も多々あります。そんな悩みを解決してくれるのが、Headless UIです。

Headless UIは、そもそもスタイルが適用されていない、機能のみを提供するコンポーネントライブラリです。TailwindCSSと同じ開発元なので、もちろんTailwindでスタイリングすることができます。他のコンポーネントライブラリに比べるとコンポーネント数は少ないのですが、基本的なパーツは揃っていますし、高機能なコンポーネントが欲しいところは、別のライブラリを使うようにしても良いと思います。

🛡️ Heroicons

https://heroicons.com/

最後は、svgアイコンを提供しているheroiconsです。こちらも開発元がTailwindCSSと同じです。そのため、tailwindでスタイリングすることを想定して作成してあります。

公式サイトからコピペすることもできますが、React用のライブラリも用意されているので、こちらを使いましょう。

npm install @heroicons/react
import { BeakerIcon } from '@heroicons/react/24/solid'

function MyComponent() {
  return (
    <div>
      <BeakerIcon className="size-6 text-blue-500" />
      <p>...</p>
    </div>
  )
}

まとめ

今回紹介したライブラリは、以下の通りです。

また、これらのライブラリを使ったReact, FastAPI, PostgreSQLのプロジェクトも筆者のGithubで公開しています。ぜひ見ていってください!

https://github.com/noknmgc/react-fastapi-template

Discussion