Behavior

docs/BEHAVIOR.md をそのまま render。下に挙動を試せる live demo

AdXpand — Behavior Rules

確認・通知・フィードバックの判断ルール。 「いつモーダルを出すか」「いつ Toast にするか」「いつ Undo を提供するか」を統一します。


0. 判断の2軸

影響の大きさ(横軸)   ×   取り消し可能性(縦軸)
  • 影響の大きさ: 自分のみ/チームに波及/顧客や課金に影響
  • 取り消し可能性: 即時 Undo 可能/後から復元可能(ゴミ箱・履歴)/不可逆

この2軸で「確認の重さ」を決めます。


1. 確認パターン早見表

状況影響復元推奨 UI
タブ切替・ソート・フィルタ自分のみ即時確認なし
お気に入り・ピン留め・テーマ切替自分のみ即時確認なし
設定保存・トグル変更自分のみ即時確認なし(自動保存)+ 微 Toast
下書き削除(Trash 行き)自分のみ後からToast + Undo(5–10秒)
アーカイブ・ステータス変更自分/チーム後からToast + Undo
メンバー招待・共有リンク発行チーム後からインライン確認 + 完了 Toast
公開状態の切替チーム/顧客即時/後からインライン確認(2段階ボタン)
メンバー解除・権限剥奪チーム不可逆寄りAlertDialog
課金プラン変更・購入顧客/課金不可AlertDialog + 金額表示
本番環境への破壊操作顧客不可AlertDialog destructive + 名前入力確認
プロジェクト/組織削除全員不可AlertDialog destructive + 名前入力確認
大量一括操作(100件以上)状況依存状況依存AlertDialog + 件数明示

2. AlertDialog(確認モーダル)を出すルール

2.1 出すべきとき

以下のどれか1つでも当てはまったら出す:

  • 復元不可能(DB drop、本番環境への破壊)
  • 課金が発生(プラン変更、有料機能購入、リソース増設)
  • 他人に影響(メンバー解除、共有解除、公開停止)
  • 大量操作の最終確定(100件以上の一括処理)

2.2 出してはいけないとき

  • 単なる保存・更新
  • 自分しか使わない設定変更
  • すぐ Undo できる操作(→ Toast + Undo を使う)
  • ログアウト(→ 即実行 + Toast)

2.3 AlertDialog の書き方ルール

import { AlertDialog } from "~/components";

<AlertDialog
  open={open}
  onOpenChange={setOpen}
  variant="destructive"           // destructive / warn / default
  title="プロジェクトを削除"        // 動詞 + 対象(疑問形にしない)
  desc="この操作は取り消せません。プロジェクト「acme-prod」とすべてのデータが削除されます。"
  confirmLabel="削除する"          // 操作名を明示。「OK」は禁止
  cancelLabel="キャンセル"
  requireText="acme-prod"         // destructive で不可逆ならテキスト入力必須
  onConfirm={async () => { await api.delete(); }}
/>

ルール:

  • confirmLabel操作名(「削除する」「アップグレードする」「招待する」)
  • confirmLabel を「OK」「はい」にしない
  • desc何が起きるか具体的に書く(×「本当に?」○「acme-prod とすべてのデータが削除されます」)
  • ✅ destructive の不可逆操作は requireText(プロジェクト名入力)を要求
  • ✅ 取り消せるなら desc に「あとで復元できます」と明記
  • confirmLabel を赤(danger)にするのは destructive のときだけ

3. Toast を使うルール

3.1 種別と用途

variant使う場面表示時間
success操作完了(保存・送信・公開)2–3秒
info状態通知(同期中・接続中)3–5秒
warn注意喚起(容量警告・期限近づく)5秒 or 手動閉じ
errorエラー(通信失敗・バリデーション)手動閉じ
progress長時間処理の進捗完了まで

3.2 Toast + Undo パターン

削除・アーカイブなど「やっちゃったけど戻せる」操作で必須。

import { toast } from "sonner";

toast.success("下書きを削除しました", {
  action: { label: "元に戻す", onClick: restore },
  duration: 8000  // Undo は長め
});

ルール:

  • ✅ Undo 可能な操作は必ず action を提供
  • ✅ Undo の表示時間は 5–10 秒(短すぎ・長すぎ NG)
  • ❌ Undo できないのに「元に戻す」ボタンを出さない(嘘 UI)

3.3 Toast にしてはいけないこと

  • ❌ 致命的エラー(→ Banner + Modal)
  • ❌ ユーザーアクションが必要なもの(→ Modal)
  • ❌ 重要な情報の唯一の表示場所(消えるので)

4. インライン確認パターン

「2段階ボタン」で確認をボタン自身に組み込む。 モーダルほど大げさじゃないが、明確な確定が欲しい時。

// React state で 2段階表示を自前実装
const [armed, setArmed] = useState(false);
useEffect(() => {
  if (!armed) return;
  const t = setTimeout(() => setArmed(false), 5000);
  return () => clearTimeout(t);
}, [armed]);

<Btn variant="danger" onClick={() => (armed ? doDelete() : setArmed(true))}>
  {armed ? "もう一度クリックで削除" : "削除"}
</Btn>

使う場面

  • 復元可能な削除
  • 公開トグル
  • 重要だがモーダルほどではない確定操作

5. フィードバック早見表

状況UI
入力中の検証エラーフィールド下に <Field error="...">(赤テキスト)
フォーム送信成功Toast success(2–3秒)
フォーム送信エラー(再試行可)Toast error + フィールドにエラーメッセージ
自動保存完了サブトル Toast or インラインインジケータ「保存済み ✓」
長時間処理(>2秒)Toast progress + 進捗% or インラインスピナー
接続断Banner(ページ上部、再接続まで表示)
サーバーエラー(500)Banner + Toast error + サポート導線
致命的(決済失敗等)Modal + 再試行ボタン + サポート連絡導線

6. 進捗とローディング

待ち時間UI
< 200ms何もしない(ちらつき防止)
200ms – 1sボタン内スピナー(押下後そのまま)
1s – 2sSkeleton(カードや表のプレースホルダー)
2s – 10sSkeleton + 「読み込み中...」テキスト
> 10sプログレスバー or 「バックグラウンドで実行中、完了したら通知」
バックグラウンドToast progress + 完了時に Toast success

7. アンチパターン(禁止)

  • 「保存しました」モーダル → Toast success で十分
  • ログアウト確認モーダル → 即実行 + Toast「ログアウトしました」
  • 何度も同じ確認 → 一度確認したらセッション中は省略 or 「次回から表示しない」を提供
  • 「OK / キャンセル」だけのボタン → 必ず操作名を書く
  • 取り消せる操作にモーダル → Toast + Undo を使う
  • モーダル on モーダル → 1階層まで(重ねない)
  • 5秒消えるエラー Toast → エラーは手動閉じ or Banner
  • 無音で破壊操作実行 → 必ず確認 or 通知
  • 「確認画面」だけのページ → モーダルで済ませる

8. 操作名のコピーライティングルール

場面NGOK
確定ボタンOK / はい削除する / 送信する / 公開する
キャンセルいいえキャンセル
削除確認本当に削除しますか?「acme-prod」を削除
完了 Toast成功しましたプロジェクトを削除しました
エラー Toastエラーが発生しました接続できませんでした。再試行してください
ローディングLoading...読み込み中...

原則:

  • 動詞は終止形(「削除する」)または体言止め(「削除」)
  • 過去形は完了 Toast のみ(「削除しました」)
  • 主語は省略(「プロジェクトを削除しました」、×「あなたのプロジェクトが削除されました」)
  • 敬語は使わない(「保存します」→「保存」)

9. デフォルト挙動の判断フロー

ユーザー操作
   ↓
取り消せる?
   ├─ いいえ(不可逆)
   │      ↓
   │   影響範囲は?
   │      ├─ 顧客/課金 → AlertDialog destructive + 名前入力
   │      ├─ チーム → AlertDialog
   │      └─ 自分のみ → AlertDialog
   │
   └─ はい
          ↓
       他人に影響?
          ├─ はい → インライン確認 → 完了 Toast
          └─ いいえ → 即実行 → Toast + Undo(破壊系のみ)

Live Demo

docs では伝わらない振る舞いを実体ボタンで

AlertDialog復元不可 / 課金 / 他人に影響 / 大量操作

ボタンラベルの命名

confirmLabel は必ず操作名を書く。「OK」「はい」は禁止。
Toast非ブロッキングなフィードバック
インライン確認モーダルほど大げさじゃない確定操作
進捗とローディング待ち時間ごとの UI

< 200ms

何もしない(ちらつき防止)

200ms – 1s

ボタン内スピナー

1s – 2s

Skeleton