# 機能設計書 95-共通UIコンポーネント

## 概要

本ドキュメントは、GiselleプラットフォームにおけるRadixベースの共有UIコンポーネントライブラリについて記述する。

### 本機能の処理概要

**業務上の目的・背景**：アプリケーション全体で一貫したデザインと操作性を提供するため、再利用可能なUIコンポーネントライブラリを提供する。Radix UIプリミティブをベースに、Tailwind CSSでスタイリングされたコンポーネントにより、開発効率とUI品質の両立を実現する。

**機能の利用シーン**：
- ダイアログ、ポップオーバー、ドロップダウンメニューの表示
- ボタン、入力フィールド、セレクトボックスの配置
- テーブル、トースト通知の表示
- アプリアイコン、ステータスバッジの表示
- ページヘッダー、空状態表示の構築

**主要な処理内容**：
1. Radix UIプリミティブのラッパー提供
2. 複数のスタイルバリアント対応（subtle, filled, solid, glass, outline等）
3. サイズバリアント対応（compact, default, large）
4. アクセシビリティ対応（フォーカス管理、キーボード操作）
5. Tailwind CSS 4によるスタイリング
6. clsx/liteによる条件付きクラス結合

**関連システム・外部連携**：
- Radix UI（アクセシブルなUIプリミティブ）
- Tailwind CSS（ユーティリティファーストCSS）
- lucide-react（アイコンライブラリ）

**権限による制御**：UIコンポーネントレベルでの権限制御なし（呼び出し側で制御）

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | 全画面 | 共通機能 | すべての画面で使用される共通UIコンポーネント |

## 機能種別

UIライブラリ / コンポーネントライブラリ

## 入力仕様

### 入力パラメータ（Button）

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| variant | ButtonStyle | No | ボタンスタイル | subtle/filled/solid/glass/outline/link/primary/destructive |
| size | ButtonSize | No | ボタンサイズ | compact/default/large |
| leftIcon | ReactNode | No | 左アイコン | - |
| rightIcon | ReactNode | No | 右アイコン | - |
| asChild | boolean | No | Slotパターン使用 | デフォルト: false |
| disabled | boolean | No | 無効状態 | - |

### 入力パラメータ（Dialog）

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| size | DialogSize | No | ダイアログサイズ | default/wide/extra-wide |
| variant | DialogVariant | No | ダイアログバリアント | default/glass/destructive |

### 入力データソース

- Reactコンポーネントプロパティ

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| JSX.Element | ReactElement | レンダリングされたUIコンポーネント |

### 出力先

- React DOM

## 処理フロー

### 処理シーケンス

```
1. コンポーネント呼び出し
   └─ Props受け取り → バリアント判定 → クラス名生成 → Radixプリミティブ/HTML要素レンダリング

2. スタイル適用
   └─ data-*属性設定 → Tailwindクラス適用 → 条件付きスタイル適用
```

### フローチャート

```mermaid
flowchart TD
    A[コンポーネント呼び出し] --> B[Props解析]
    B --> C[バリアント判定]
    C --> D[サイズ判定]
    D --> E[clsxでクラス名結合]
    E --> F{asChild?}
    F -->|Yes| G[Slot.Root使用]
    F -->|No| H[HTML要素使用]
    G --> I[子要素にprops転送]
    H --> J[直接レンダリング]
    I --> K[DOM出力]
    J --> K
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | バリアントスタイル | data-style属性でTailwindセレクターを制御 | 常時 |
| BR-002 | サイズスタイル | data-size属性でサイズバリアントを制御 | 常時 |
| BR-003 | フォーカス表示 | focus-visible:ringでフォーカス状態を可視化 | キーボード操作時 |
| BR-004 | 無効状態 | disabled:opacity-50で視覚的フィードバック | disabled=true |
| BR-005 | Slotパターン | asChild=trueで子要素にprops転送 | asChild使用時 |

### 計算ロジック

特になし

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

該当なし（純粋なUIコンポーネント）

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | - | - | UIコンポーネントのため特別なエラー処理なし |

### リトライ仕様

該当なし

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

該当なし

## パフォーマンス要件

- 軽量なコンポーネント実装
- 不要な再レンダリングの防止

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

- XSS防止（React標準のエスケープ）

## 備考

- Radix UIのアクセシビリティ機能を継承
- Tailwind CSS 4の新機能を活用（CSS変数ベースのカスタムプロパティ）

---

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

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

### 推奨読解順序

#### Step 1: ユーティリティを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | utils.ts | `internal-packages/ui/utils.ts` | isIconName関数（lucide-react連携） |

**読解のコツ**: iconNamesの型が実行時に異なる形式（array/Set/object）になる可能性への対応を確認。

#### Step 2: 基本コンポーネントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | button.tsx | `internal-packages/ui/components/button.tsx` | Buttonコンポーネントの実装パターン |
| 2-2 | input.tsx | `internal-packages/ui/components/input.tsx` | 入力フィールドの実装 |
| 2-3 | select.tsx | `internal-packages/ui/components/select.tsx` | セレクトボックスの実装 |

**主要処理フロー（button.tsx）**:
1. **1-21行目**: 型定義（ButtonStyle, ButtonSize, ButtonProps）
2. **23-33行目**: Buttonコンポーネント定義、Props分解
3. **34-37行目**: asChildによるコンポーネント切替（Slot.Root or button）
4. **39-61行目**: clsxによるクラス名生成（バリアント・サイズ対応）
5. **62-65行目**: data-*属性設定
6. **67-72行目**: glassバリアントの背景レイヤー
7. **73-115行目**: leftIcon、children、rightIconのレンダリング

#### Step 3: オーバーレイコンポーネントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | dialog.tsx | `internal-packages/ui/components/dialog.tsx` | Dialogコンポーネントの実装 |
| 3-2 | popover.tsx | `internal-packages/ui/components/popover.tsx` | Popoverの実装 |
| 3-3 | dropdown-menu.tsx | `internal-packages/ui/components/dropdown-menu.tsx` | DropdownMenuの実装 |

**主要処理フロー（dialog.tsx）**:
1. **6-9行目**: Radix DialogプリミティブのRe-export
2. **11-19行目**: サイズ・バリアント型定義
3. **21-95行目**: DialogContent実装（glass/defaultバリアント分岐）
4. **97-148行目**: DialogTitle, DialogDescription, DialogFooter, DialogHeader, DialogBody

#### Step 4: 表示コンポーネントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | table.tsx | `internal-packages/ui/components/table.tsx` | テーブルコンポーネント |
| 4-2 | toast.tsx | `internal-packages/ui/components/toast.tsx` | トースト通知 |
| 4-3 | status-badge.tsx | `internal-packages/ui/components/status-badge.tsx` | ステータスバッジ |
| 4-4 | app-icon.tsx | `internal-packages/ui/components/app-icon.tsx` | アプリアイコン |

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

```
UIコンポーネント
    │
    ├─ Button
    │      ├─ Slot.Root (asChild=true)
    │      └─ button要素 (asChild=false)
    │
    ├─ Dialog
    │      ├─ DialogPrimitive.Root
    │      ├─ DialogPrimitive.Portal
    │      ├─ DialogPrimitive.Overlay
    │      ├─ DialogPrimitive.Content
    │      │      └─ GlassSurfaceLayers
    │      ├─ DialogPrimitive.Title
    │      └─ DialogPrimitive.Description
    │
    ├─ Popover
    │      ├─ PopoverPrimitive.Root
    │      ├─ PopoverPrimitive.Trigger
    │      └─ PopoverPrimitive.Content
    │
    └─ DropdownMenu
           ├─ DropdownMenuPrimitive.Root
           ├─ DropdownMenuPrimitive.Trigger
           ├─ DropdownMenuPrimitive.Content
           └─ DropdownMenuPrimitive.Item
```

### データフロー図

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

Props ───────────────────┐
                         │
variant ─────────────────┼──▶ clsxクラス生成 ──▶ className
                         │
size ────────────────────┤
                         │
children ────────────────┼──▶ Radix/HTML要素 ──▶ JSX.Element
                         │
leftIcon/rightIcon ──────┘
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| button.tsx | `internal-packages/ui/components/button.tsx` | ソース | Buttonコンポーネント |
| dialog.tsx | `internal-packages/ui/components/dialog.tsx` | ソース | Dialogコンポーネント |
| popover.tsx | `internal-packages/ui/components/popover.tsx` | ソース | Popoverコンポーネント |
| dropdown-menu.tsx | `internal-packages/ui/components/dropdown-menu.tsx` | ソース | DropdownMenuコンポーネント |
| input.tsx | `internal-packages/ui/components/input.tsx` | ソース | Inputコンポーネント |
| select.tsx | `internal-packages/ui/components/select.tsx` | ソース | Selectコンポーネント |
| table.tsx | `internal-packages/ui/components/table.tsx` | ソース | Tableコンポーネント |
| toast.tsx | `internal-packages/ui/components/toast.tsx` | ソース | Toastコンポーネント |
| toggle.tsx | `internal-packages/ui/components/toggle.tsx` | ソース | Toggleコンポーネント |
| status-badge.tsx | `internal-packages/ui/components/status-badge.tsx` | ソース | StatusBadgeコンポーネント |
| app-icon.tsx | `internal-packages/ui/components/app-icon.tsx` | ソース | AppIconコンポーネント |
| glass-surface.tsx | `internal-packages/ui/components/glass-surface.tsx` | ソース | GlassSurfaceコンポーネント |
| page-heading.tsx | `internal-packages/ui/components/page-heading.tsx` | ソース | PageHeadingコンポーネント |
| empty-state.tsx | `internal-packages/ui/components/empty-state.tsx` | ソース | EmptyStateコンポーネント |
| search-input.tsx | `internal-packages/ui/components/search-input.tsx` | ソース | SearchInputコンポーネント |
| tab-navigation.tsx | `internal-packages/ui/components/tab-navigation.tsx` | ソース | TabNavigationコンポーネント |
| docs-link.tsx | `internal-packages/ui/components/docs-link.tsx` | ソース | DocsLinkコンポーネント |
| utils.ts | `internal-packages/ui/utils.ts` | ソース | ユーティリティ関数 |
