# 機能設計書 14-バリアント管理（Variants）

## 概要

本ドキュメントは、バリアント（hover・focus・responsive等の修飾子）の登録・適用・ソート・比較を管理するVariantsクラスの設計について記述する。static・functional・compound・arbitraryの各種バリアントに対応する。

### 本機能の処理概要

Variantsクラスは、Tailwind CSSのバリアントシステムの中核であり、全バリアントの登録・管理・適用・ソート比較を担当する。バリアントはユーティリティクラスに条件付きスタイルを適用する修飾子であり、`hover:text-blue-500` の `hover:` 部分に相当する。

**業務上の目的・背景**：Tailwind CSSでは、ユーティリティクラスに対してレスポンシブブレイクポイント、疑似クラス、メディアクエリなどの条件を付与するバリアントシステムが不可欠である。Variantsクラスはこれらの修飾子を一元管理し、正しい順序でCSSルールを出力するための基盤を提供する。

**機能の利用シーン**：`hover:bg-blue-500` のような条件付きスタイルを解決する際、`@custom-variant` でカスタムバリアントを登録する際、CSS出力時にバリアントの順序を決定する際に使用される。

**主要な処理内容**：
1. staticバリアントの登録: `hover`、`focus` 等の固定バリアントをapplyFnとともに登録する
2. functionalバリアントの登録: `@media`、`@container` 等のパラメータ付きバリアントを登録する
3. compoundバリアントの登録: `group-*`、`peer-*` 等の合成バリアントを登録する
4. fromAstによるAST定義からのバリアント登録: `@custom-variant` のボディからバリアントを生成する
5. バリアントの比較・ソート: 登録順序に基づくバリアントの比較関数を提供する
6. グループ化: 関連バリアントをグループ化し、グループ内の比較関数をカスタマイズする
7. compound互換性チェック: 2つのバリアントが合成可能かどうかを判定する
8. createVariants関数: 全組み込みバリアント（hover, focus, responsive等）の登録

**関連システム・外部連携**：DesignSystem（design-system.ts）から参照される。candidate.ts のparseVariant関数からバリアントの種別判定に使用される。compile.ts のapplyVariant関数からバリアントの適用に使用される。

**権限による制御**：権限による制御は存在しない。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 5 | レイアウト | 補助機能 | htmlタグの[&_h1]:font-thin任意値バリアントを処理し、バリアントルールを適用する |

## 機能種別

データ管理 / CSS変換処理 / ソート処理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| name | string | Yes | バリアント名（例: `hover`, `focus`, `@media`） | IS_VALID_VARIANT_NAMEの正規表現に一致 |
| applyFn | VariantFn | Yes | ルールにバリアントを適用する関数 | 関数型 |
| compounds | Compounds | No | バリアントが生成するルールの種別（AtRules / StyleRules） | Compounds enum |
| compoundsWith | Compounds | No（compound専用） | 合成可能なルール種別 | Compounds enum |
| order | number | No | ソート順序の明示指定 | 正の整数 |

### 入力データソース

- createVariants関数によるハードコードされた組み込みバリアント定義
- `@custom-variant` ディレクティブによるカスタムバリアント定義
- v3互換プラグインAPI経由のバリアント定義

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| variant | VariantInfo | バリアントのメタ情報（kind, order, applyFn, compounds） |
| compareResult | number | バリアント比較の結果（-1, 0, 1） |
| completions | string[] | 補完候補の文字列配列 |

### 出力先

- compile.ts のapplyVariant関数を通じてCSS出力に反映
- IntelliSense（intellisense.ts）を通じてIDE補完機能に提供

## 処理フロー

### 処理シーケンス

```
1. バリアントの登録
   ├─ static(): 固定バリアントを登録（order自動付与）
   ├─ functional(): パラメータ付きバリアントを登録
   ├─ compound(): 合成バリアントを登録（compoundsWith指定）
   ├─ fromAst(): ASTからバリアントを生成して登録
   └─ group(): 関連バリアントをグループ化（同一order）

2. バリアントの検索・取得
   ├─ has(name): バリアントの存在確認
   ├─ get(name): バリアント情報の取得
   ├─ kind(name): バリアントの種別取得
   └─ compoundsWith(parent, child): 合成互換性チェック

3. バリアントの比較・ソート
   └─ compare(a, z): 2つのバリアントの順序比較
       ├─ arbitrary バリアントはセレクタで比較
       ├─ 登録順序（order）で比較
       ├─ compound内はvariant同士を再帰比較
       └─ グループ内はカスタム比較関数を使用
```

### フローチャート

```mermaid
flowchart TD
    A[バリアント比較要求] --> B{同一バリアント?}
    B -->|Yes| C["0 を返す"]
    B -->|No| D{arbitrary?}
    D -->|両方| E["セレクタで比較"]
    D -->|片方のみ| F["arbitraryを後方に"]
    D -->|なし| G["order で比較"]
    G --> H{order が異なる?}
    H -->|Yes| I["order 差を返す"]
    H -->|No| J{compound?}
    J -->|Yes| K["内部variantを再帰比較"]
    J -->|No| L{カスタム比較関数あり?}
    L -->|Yes| M["カスタム比較関数を使用"]
    L -->|No| N["root名で比較"]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-14-01 | 登録順序 | バリアントは登録順序でソートされる。グループ内は同一orderを持つ | 常時 |
| BR-14-02 | compound互換性 | compoundバリアントは、子バリアントのcompounds種別がparentのcompoundsWith種別と一致する場合にのみ合成可能 | compoundsWith チェック時 |
| BR-14-03 | Compounds.Never | Compounds.Never が設定されたバリアントは合成不可能 | compound互換性チェック時 |
| BR-14-04 | 既存上書き | 同名バリアントが再登録された場合、既存のkind・applyFn・compoundsが上書きされる（orderは維持） | バリアント再登録時 |
| BR-14-05 | arbitrary順序 | arbitraryバリアントは常に名前付きバリアントより後方にソートされる | compare実行時 |
| BR-14-06 | 名前規則 | バリアント名は `@?[a-z0-9][a-zA-Z0-9_-]*` に一致する必要がある（末尾はアンダースコア・ハイフン不可） | バリアント名バリデーション時 |

### 計算ロジック

Compounds ビットフラグによる合成互換性判定: `(parentInfo.compoundsWith & childInfo.compounds) !== 0` で互換性を判定する。AtRules と StyleRules の2種類のルールタイプがビットフラグで管理される。

## データベース操作仕様

本機能はデータベースを使用しない。バリアント登録情報はインメモリの `Map<string, VariantInfo>` で管理される。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | - | バリアントの適用失敗 | applyFn が null を返す場合、バリアントは適用されず無視される |

### リトライ仕様

リトライ処理は存在しない。

## トランザクション仕様

トランザクション管理は存在しない。

## パフォーマンス要件

- バリアントの検索は `Map.get()` による O(1) アクセス
- compare関数はソート時に頻繁に呼び出されるため、効率的な実装が必要

## セキュリティ考慮事項

バリアントの処理はCSS仕様の範囲内で行われる。

## 備考

- createVariants関数はvariants.tsの後半に配置され、全組み込みバリアント（hover, focus, active, responsive, dark, print等）を登録する
- Compounds enumはビットフラグとして定義され、Never(0), AtRules(1), StyleRules(2) を持つ
- IS_VALID_VARIANT_NAME は `/^@?[a-z0-9][a-zA-Z0-9_-]*(?<![_-])$/` の正規表現

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

バリアント関連の型定義とフラグを把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | variants.ts | `packages/tailwindcss/src/variants.ts` | VariantFn型（26-29行目）: ルールとバリアントを受け取り適用する関数型 |
| 1-2 | variants.ts | `packages/tailwindcss/src/variants.ts` | Compounds enum（33-37行目）: Never / AtRules / StyleRules のビットフラグ |
| 1-3 | candidate.ts | `packages/tailwindcss/src/candidate.ts` | Variant 型（103-162行目）: arbitrary / static / functional / compound の4種類 |

**読解のコツ**: Compounds はビットフラグであり、`|` で結合、`&` でチェックするパターンで使用される。`Never = 0` は全ビットが0であり、どの条件にもマッチしないことを意味する。

#### Step 2: Variantsクラスを理解する

レジストリとしてのVariantsクラスの構造を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | variants.ts | `packages/tailwindcss/src/variants.ts` | Variantsクラス（39-317行目）: variants Map, compareFns Map, lastOrder 等の内部状態 |

**主要処理フロー**:
1. **72-84行目**: `static()` - 固定バリアントの登録。compounds のデフォルトは StyleRules
2. **86-109行目**: `fromAst()` - AST定義からバリアントを生成。@slot の置換を含む
3. **112-124行目**: `functional()` - パラメータ付きバリアントの登録
4. **126-139行目**: `compound()` - 合成バリアントの登録。compoundsWith を指定
5. **141-146行目**: `group()` - 関連バリアントのグループ化。同一orderを共有
6. **160-193行目**: `compoundsWith()` - 合成互換性チェック
7. **203-270行目**: `compare()` - バリアントの順序比較

#### Step 3: 組み込みバリアント登録を理解する

createVariants関数による組み込みバリアントの登録を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | variants.ts | `packages/tailwindcss/src/variants.ts` | createVariants関数（348行目以降）: 全組み込みバリアントの登録。staticVariant, negateConditions 等のヘルパー関数 |

**主要処理フロー**:
- **348-352行目**: createVariants関数の開始。Variantsインスタンス生成
- **357-371行目**: staticVariant ヘルパー関数。セレクタからバリアントを生成
- **373-374行目**: `*` と `**` バリアントの登録（子要素・子孫要素セレクタ）

### プログラム呼び出し階層図

```
DesignSystem (design-system.ts)
    │
    ├─ createVariants(theme) → Variants インスタンス生成
    │      ├─ staticVariant() を多数呼び出し（hover, focus等）
    │      ├─ variants.functional() を呼び出し（@media等）
    │      └─ variants.compound() を呼び出し（group-*, peer-*）
    │
    ├─ Variants.has(name) ← parseVariant から参照
    │
    ├─ Variants.get(name) ← applyVariant から参照
    │      └─ applyFn(rule, variant) → ルールを変更
    │
    ├─ Variants.compare(a, z) ← compileCandidates のソートで使用
    │
    └─ Variants.compoundsWith(parent, child) ← parseCandidate で使用
```

### データフロー図

```
[入力]                          [処理]                        [出力]

createVariants(theme)  ───▶  Variants.static()        ───▶  variants Map に登録
                             Variants.functional()
                             Variants.compound()

parseVariant(string)   ───▶  Variants.has(name)       ───▶  種別判定結果
                             Variants.kind(name)

applyVariant(rule, v)  ───▶  Variants.get(name)       ───▶  変更されたCSS Rule
                             applyFn(rule, variant)

ソート要求              ───▶  Variants.compare(a, z)   ───▶  比較結果 (-1/0/1)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| variants.ts | `packages/tailwindcss/src/variants.ts` | ソース | Variantsクラス本体と全組み込みバリアント定義 |
| candidate.ts | `packages/tailwindcss/src/candidate.ts` | ソース | Variant型定義。parseVariant関数 |
| compile.ts | `packages/tailwindcss/src/compile.ts` | ソース | applyVariant関数。バリアントのCSS適用 |
| design-system.ts | `packages/tailwindcss/src/design-system.ts` | ソース | Variantsインスタンスの生成と保持 |
| index.ts | `packages/tailwindcss/src/index.ts` | ソース | @custom-variant ディレクティブの処理 |
| ast.ts | `packages/tailwindcss/src/ast.ts` | ソース | Rule・StyleRule・AtRule型の定義 |
| default-map.ts | `packages/tailwindcss/src/utils/default-map.ts` | ソース | DefaultMap - バリアント登録のストレージ |
| compare-breakpoints.ts | `packages/tailwindcss/src/utils/compare-breakpoints.ts` | ソース | レスポンシブバリアントの比較関数 |
