2025年7月2日

【備忘録】カスタムデザインシステムのtailwind cssのeslint設定方法

✅ 前提

このルールは "className" に直接文字列で Tailwind クラスを記述している場合に有効です。 例:

<div className="btn-primary text-heading" />

🧩 1. eslint-plugin-tailwindcss をインストール

npm install --save-dev eslint-plugin-tailwindcss

または

yarn add -D eslint-plugin-tailwindcss

🛠 2. .eslintrc.js に設定を追加

以下のように ESLint 設定に tailwindcss プラグインと no-custom-classname を追加します。

// .eslintrc.js
module.exports = {
  plugins: ['tailwindcss'],
  extends: ['plugin:tailwindcss/recommended'],
  rules: {
    'tailwindcss/no-custom-classname': [
      'error',
      {
        whitelist: [
          // ✅ デザインシステムで許可されたカスタムユーティリティ
          'btn-primary',
          'btn-secondary',
          'text-heading',
          'bg-surface',
          'text-error',
          'container',
          'mx-auto',
          'px-4',
          'py-2',
          // Tailwindの公式ユーティリティはデフォルトで許可されます
        ],
      },
    ],
  },
}

📌 ポイント

  • whitelist に書いたクラスだけが許可されます。
  • デフォルトで Tailwind の公式ユーティリティは許可されます。
  • 独自の btn-*text-* などのカスタムクラスを制御したいときに有効です。

🧪 3. テスト

以下のようなコードで ESLint が検知してくれるか確認してください。

// ✅ OK
<div className="btn-primary text-heading" />

// ❌ NG(whitelistにない)
<div className="text-red-500 custom-class" />

⚠️ 注意点

  • このルールは文字列リテラルでのクラス記述にしか効きません。
  • clsx()classnames() などでクラスを組み立てている場合には一部しか検出できません。

🧠 補足:class名が長すぎて辛いときは…

クラス名をまとめて tailwind.config.js に記述して require() で読み込むこともできます:

// allowedTailwindClasses.js
module.exports = [
  'btn-primary',
  'btn-secondary',
  'text-heading',
  'bg-surface',
  // ...
]
// .eslintrc.js
const whitelist = require('./allowedTailwindClasses.js')

module.exports = {
  rules: {
    'tailwindcss/no-custom-classname': ['error', { whitelist }],
  },
}

🚀 おまけ

この仕組みで、

  • デザインシステムのクラス使用の強制
  • Tailwind非推奨のクラスを明示的に弾く という自動チェックが実現できます。

正規表現で公式のユーティリティクラスを制限する方法(まだ試してない)

.eslintrc.json に追記する内容

まず、プラグインをインストールしてください:

npm install --save-dev eslint-plugin-regexp

そして .eslintrc.json に以下のように設定を追加します:

{
  "plugins": ["regexp"],
  "rules": {
    "regexp/match": [
      "error",
      {
        "files": {
          "include": ["src/**/*.{js,jsx,ts,tsx}"]
        },
        "regex": [
          {
            "pattern": "\\b(text|bg|border|ring)-(red|gray|blue|green|yellow|pink|indigo|purple|emerald|cyan)-(100|200|300|400|500|600|700|800|900)\\b",
            "message": "カラーの直接指定は禁止です。デザインシステムのユーティリティ(例: text-error)を使ってください。"
          },
          {
            "pattern": "\\b(p[trblxy]?|m[trblxy]?)-[3-9]\\b",
            "message": "自由な余白指定は禁止です。デザインシステムのspacingユーティリティを使ってください(例: px-4)。"
          }
        ]
      }
    ]
  }
}

💡 ファイル構成の例

.eslintrc.json
package.json
src/
  └ components/
      └ Button.tsx

この状態で text-red-500px-7 を使うと ESLint が以下のようなエラーを出してくれます。

[eslint] カラーの直接指定は禁止です。デザインシステムのユーティリティ(例: text-error)を使ってください。

✅ チェック方法

以下のコマンドで ESLint を実行できます:

npx eslint "src/**/*.{ts,tsx,js,jsx}"

🚀 応用もできます

  • regex 配列にさらにパターンを追加すれば、例えば shadow-* なども制限可能
  • 別ファイルに禁止クラスの一覧を定義して、require() で読み込むのは .js 設定でのみ可能ですが、.json に変換した形式でも読み込ませる工夫は可能です(要ビルドスクリプト)

必要なら、よく使う 禁止パターンの正規表現集他チームでも使える共有JSONテンプレート も作成できます。お気軽にどうぞ!