# 通知設計書 23-成功通知

## 概要

本ドキュメントは、操作が成功した際に表示される緑色のトースト通知「成功通知」の設計仕様を定義する。ユーザーの操作が正常に完了したことを視覚的にフィードバックし、安心感を与えるUI通知である。

### 本通知の処理概要

成功通知（Success Toast）は、アプリケーション内でユーザーの操作が正常に完了したことを通知するためのUI通知コンポーネントである。データの保存、設定の更新、処理の完了など、ポジティブな結果をユーザーに伝達する。

**業務上の目的・背景**：ユーザーがアプリケーション上で何らかの操作を行った際、その結果を即座にフィードバックすることは、ユーザー体験の向上に不可欠である。成功通知は、操作が意図通りに完了したことを明確に伝え、ユーザーに安心感と達成感を提供する。特にフォーム送信、データ保存、ワークフロー実行完了など、ユーザーが結果を確認したい操作において重要な役割を果たす。緑色のビジュアルスタイルは、世界的に「成功」「完了」「OK」を示す色として認識されており、直感的な理解を促進する。

**通知の送信タイミング**：アプリケーション内で操作が正常に完了した直後にリアルタイムで表示される。具体的には、toast関数にtype: 'success'を指定して呼び出した際、または成功を示す処理完了後のコールバック内で即座に画面右下にトースト通知が表示される。

**通知の受信者**：現在アプリケーションを操作中のユーザー本人のみが受信する。成功通知はクライアントサイドで生成され、操作を行ったユーザーのブラウザのみに表示される。他のユーザーや外部システムには一切送信されない。

**通知内容の概要**：トースト通知には、メッセージ（message）が必須で、オプションとしてタイトル（title）、アクションボタン（action）を含めることができる。成功通知は緑色のグラデーションスタイルで表示され、視覚的に成功・完了を示す。テキストは--color-successカラートークンで定義された色で表示される。

**期待されるアクション**：ユーザーは成功通知を確認し、操作が正常に完了したことを認識する。必要に応じてアクションボタンをクリックするか、閉じるボタン（X）で通知を消去する。成功通知は確認のみを目的としており、追加のアクションは必ずしも必要ではない。

## 通知種別

アプリ内通知（Toast / UI通知）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期（クライアントサイド） |
| 優先度 | 中 |
| リトライ | なし（クライアントサイド表示のため） |

### 送信先決定ロジック

- 現在のブラウザセッションでアプリケーションを操作中のユーザー
- ToastProviderコンポーネントがレンダリングされている画面のみ

## 通知テンプレート

### UI通知の場合

| 項目 | 内容 |
|-----|------|
| 表示位置 | 画面右下（bottom-right） |
| 幅 | 360px（最大100vw） |
| 背景色 | 緑色グラデーション（--color-success系） |
| 形式 | Glass morphism UI |

### 本文テンプレート

```
┌──────────────────────────────────────┐
│ [タイトル（オプション）]           [X] │
│ メッセージ本文                        │
│                      [アクションボタン]│
└──────────────────────────────────────┘
```

### 添付ファイル

| ファイル名 | 形式 | 条件 | 説明 |
|----------|------|------|------|
| なし | - | - | UI通知のため添付ファイルなし |

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| message | 通知メッセージ本文 | 呼び出し元コンポーネント | Yes |
| title | 通知タイトル | 呼び出し元コンポーネント | No |
| id | トーストの一意識別子 | 自動生成またはオプション指定 | No |
| preserve | 自動消去の有無 | オプション（デフォルト: true） | No |
| action.label | アクションボタンのラベル | オプション | No |
| action.onClick | アクションボタンのクリックハンドラ | オプション | No |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| 画面操作 | toast()関数呼び出し | type='success' | 汎用トースト関数による成功通知 |
| 処理完了 | 非同期処理の成功コールバック | 処理が正常完了した場合 | API呼び出しやデータ保存の完了時 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| ToastProvider未配置 | ToastProviderがコンポーネントツリーに存在しない場合はエラー |
| SSRコンテキスト | サーバーサイドレンダリング中は表示されない |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[操作成功イベント] --> B[toast関数呼び出し type=success]
    B --> C{ToastContext存在?}
    C -->|Yes| D[トーストID生成/取得]
    C -->|No| E[エラースロー]
    D --> F[toasts配列に追加/更新]
    F --> G[ToastPrimitive.Root描画]
    G --> H[緑色スタイルで表示]
    H --> I{preserve=true?}
    I -->|Yes| J[手動クローズ待機]
    I -->|No| K[自動消去]
    J --> L[dismiss呼び出し]
    K --> L
    L --> M[toasts配列から削除]
    M --> N[終了]
    E --> N
```

## データベース参照・更新仕様

### 参照テーブル一覧

| テーブル名 | 用途 | 備考 |
|-----------|------|------|
| なし | - | クライアントサイドのみで完結するためDB参照なし |

### 更新テーブル一覧

| テーブル名 | 操作 | 概要 |
|-----------|------|------|
| なし | - | クライアントサイドのみで完結するためDB更新なし |

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| Context未定義エラー | ToastProviderの外でuseToastsを呼び出し | "useToast must be used within a ToastProvider"エラーをスロー |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | なし |
| リトライ間隔 | - |
| リトライ対象エラー | - |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | なし（制限なし） |
| 1日あたり上限 | なし（制限なし） |

### 配信時間帯

制限なし（24時間、ユーザー操作に応じて即時表示）

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

- トースト通知は現在のユーザーセッションでのみ表示され、他ユーザーには漏洩しない
- XSS対策としてReactのエスケープ機能により、メッセージ内のHTMLはエスケープされる
- 機密情報はトースト通知に含めないこと

## 備考

- 実装ファイル: `internal-packages/ui/components/toast.tsx`
- Radix UIのToastプリミティブを使用
- Tailwind CSSでスタイリング
- カラートークン: --color-success
- 情報通知（info）との違いは表示色のみ（緑 vs 青）

---

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

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

### 推奨読解順序

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

まず、トースト通知のデータ構造（インターフェース）を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | toast.tsx | `internal-packages/ui/components/toast.tsx` | Toastインターフェース（18-25行目）でtype: "success"が定義されていることを確認 |

**読解のコツ**: type: "success"の場合、スタイルがどのように適用されるかを追跡する。

#### Step 2: スタイリングを理解する

成功通知に適用される緑色スタイルを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | toast.tsx | `internal-packages/ui/components/toast.tsx` | ToastPrimitive.Root内のclsx（153-165行目）でdata-[type=success]のスタイルを確認 |

**主要処理フロー**:
1. **148行目**: data-type={toast.type}でtype属性をDOMに設定
2. **158行目**: data-[type=success]:bg-linear-to-b で緑色グラデーション背景を適用
3. **163行目**: data-[type=success]:ring-[color:var(--color-success)]/25 でリングカラーを適用

#### Step 3: テキストカラーを理解する

成功通知のテキストに適用される色を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | toast.tsx | `internal-packages/ui/components/toast.tsx` | ToastPrimitive.Title内（172-210行目）でgroup-data-[type=success]のテキスト色を確認 |

**主要処理フロー**:
- **177行目**: group-data-[type=success]:text-[color:var(--color-success)] でタイトルテキスト色
- **189行目**: group-data-[type=success]:text-[color:var(--color-success)]/70 で説明テキスト色（やや薄め）

#### Step 4: トースト呼び出し方法を理解する

成功通知を表示するための呼び出し方法を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | toast.tsx | `internal-packages/ui/components/toast.tsx` | _toast関数（104-120行目）でtype: "success"を指定する方法 |

**主要処理フロー**:
- toast(message, { type: "success" })で成功通知を表示
- 専用のsuccess()ショートカット関数は定義されていない（info, errorのみ）

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

```
toast(message, { type: "success" })
    |
    +-- _toast() (内部関数)
          |
          +-- upsertToastArray()
          |     |
          |     +-- { ...options, type: "success" }
          |
          +-- setToasts()
                |
                +-- React State更新
                      |
                      +-- ToastPrimitive.Root再レンダリング
                            |
                            +-- data-type="success"
                                  |
                                  +-- 緑色スタイル適用
```

### データフロー図

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

toast(message, { type: "success" }) ───> _toast()
                                              |
                                              v
                                    upsertToastArray()
                                              |
                                              v
                                    { id, message, type: "success", ... }
                                              |
                                              v
                                    [React State: toasts[]]
                                              |
                                              v
                                    toasts.map(render)
                                              |
                                              v
                                    <ToastPrimitive.Root data-type="success">
                                              |
                                              v
                                    bg-linear-to-b from-[--color-success]
                                              |
                                              v
                                    画面右下に緑色トースト表示
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| toast.tsx | `internal-packages/ui/components/toast.tsx` | ソース | トースト通知コンポーネント・フック |
| index.ts | `internal-packages/ui/components/index.ts` | ソース | コンポーネントエクスポート |
| package.json | `internal-packages/ui/package.json` | 設定 | 依存関係定義（radix-ui, clsx） |
