AIアシスタント(LLM)とユーザーが対話するためのインターフェース。メッセージバブル・ストリーミングテキスト表示・ロール別スタイリング(user / assistant / system)・入力欄・送信ボタン・ローディング状態・エラー状態で構成される複合UIコンポーネント。ChatGPT・Claude・Geminiなどのチャットインターフェースの設計パターンが標準化しつつあり、プロダクト内AIアシスタント・カスタマーサポートbot・コードアシスタントなど幅広い用途で使われる。
この記事を読むと、user/assistant/systemのロール別レイアウト・ストリーミング表示のアニメーション・Markdown内容のレンダリング・入力欄の高さ自動調整・aria-live でのストリーミング通知・中断ボタンの設計が自分でできるようになります。
1. UI例(Preview / Live)
実装で見る(GunjoUI)
この部品を、デザインシステム GUNJO の実装で確かめられます。
2. 定義(Definition)
LLM(大規模言語モデル)または会話型AIとユーザーが対話するためのUIコンポーネント群の総称。
メッセージのロール:
| ロール | 説明 | 表示位置 |
|---|---|---|
user | ユーザーの入力 | 右寄せ・青系バブル |
assistant | AIの応答 | 左寄せ・グレー系バブル |
system | システムプロンプト(通常非表示) | UIに表示しないことが多い |
3. 使い分け(When to use / When NOT to use)
3.1 When to use
- AIアシスタント機能:製品内の質問応答・コンテキスト理解が必要なヘルプ
- カスタマーサポートbot:FAQの自動応答・エスカレーション前の一次対応
- コードアシスタント:コードの説明・バグ修正・リファクタリング提案
- コンテンツ生成支援:文章の下書き・翻訳・要約
3.2 When NOT to use
- 定型の手続き:フォームやウィザードの方が適切(住所入力・アカウント設定)
- 単純なFAQ:検索可能なFAQページの方が早い
- リアルタイム性が不要で構造化された選択:決定木形式のbotの方が予測可能
4. 設計判断の核(Decision Principles)
AI Chat UIの核は「ストリーミング中の状態管理」——AIの応答はストリーミング(逐次表示)で返ってくることが多く、「考え中」→「テキスト生成中」→「完了」の3状態を適切に表示することが、体感速度とユーザーの安心感に直結する。
判断の優先順位:① ストリーミング状態の表示 → ② 中断ボタンの提供 → ③ エラー状態の設計 → ④ aria-live でのアクセシビリティ
- 「考え中」はドットアニメーション、「生成中」はカーソル点滅で区別する:APIの応答が来るまでの待機中はドット3つのバウンスアニメーション、テキストが流れてくるストリーミング中はテキスト末尾のカーソル点滅を表示することで、ユーザーは「処理の段階」を直感的に理解できる
- 中断ボタンを必ず提供する:ストリーミング中はテキストが長くなる可能性があり、ユーザーが途中で止めたいケースは多い。送信ボタンをストリーミング中は「停止ボタン(■)」に切り替えるUI変化が最も明確
- エラー状態は応答バブル内にインライン表示し「再試行」ボタンを提供する:エラーをモーダルやトーストで表示すると、どのメッセージに対するエラーか分からなくなる。該当のAI応答バブルの位置に赤系のエラーバブルを表示し、再試行ボタンをその直下に配置する
- テキストエリアは入力量に合わせて自動高さ調整する:
textareaの高さをscrollHeightに合わせて自動伸長し、最大高さ(例:120px)を超えたらスクロール可能にする
5. 状態設計(States)
| 状態 | 入力欄 | 送信ボタン | AI応答エリア |
|---|---|---|---|
| 初期(空) | プレースホルダー表示 | 非活性 | なし |
| 入力中 | テキスト表示 | 活性 | — |
| 考え中(waiting) | disabled | — | ドットアニメーション |
| 生成中(streaming) | disabled | 停止ボタン(■) | テキスト逐次表示+カーソル |
| 完了 | 再び有効 | 送信ボタン | 完全なテキスト |
| エラー | 再び有効 | 送信ボタン | エラーバブル+再試行 |
6. バリエーション設計(Variants)
| バリアント | 特徴 | 使用例 |
|---|---|---|
| 全画面チャット | メッセージ履歴が主役 | ChatGPT・Claude |
| サイドパネル型 | コンテンツと並列表示 | エディタのAIアシスタント |
| ポップオーバー型 | 小さなウィジェットとして展開 | サポートbot・Intercom |
| インライン型 | テキスト選択後その場でAI操作 | Notion AI・Word Copilot |
7. パターン集(Good / Bad / How to fix)
7.0 よく崩れる設計パターン(3つ)
- ストリーミング中に入力が可能:前のメッセージの応答中に次のメッセージを送信でき、会話の順序が破綻する
- エラー時に再試行手段がない:API呼び出しが失敗したとき、ユーザーは同じメッセージを手動でコピーして再入力する必要がある
- メッセージ追加後にスクロールしない:新しいメッセージが表示されるたびに自動スクロールされず、ユーザーが手動でスクロールする必要がある
7.1 Bad(典型3つ)
- ストリーミング中も
<textarea>が有効で複数のリクエストを連続送信できる - AI応答のエラーをページ上部のトーストで通知し、どのメッセージのエラーか不明
<div>のスクロールコンテナにscrollTopの自動制御がなく新メッセージを見逃す
7.2 Good(対になる3つ)
isStreamingstate で<textarea>と送信ボタンをdisabledにし、ストリーミング中は停止ボタンのみ表示する- エラーバブルを当該メッセージ位置に赤系スタイルでインライン表示し、直下に「↺ 再試行」ボタンを配置する
useEffect(() => { messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' }); }, [messages, streamingText])で自動スクロールを実装する
7.3 How to fix(手順)
isStreamingstate で入力欄とボタンの活性/非活性を制御する- ストリーミング中の送信ボタンを「停止(■)」に切り替え、クリックでストリーミングをキャンセルする
- エラーはメッセージバブルの位置にインラインで表示し、再試行ボタンを提供する
- メッセージリスト末尾に
refを置き、scrollIntoViewで自動スクロールする
8. ルール(Must / Better)
Must(守らないと壊れる)
Better(品質が跳ねる)
9. アクセシビリティ要件(必須)
Screen Reader
<!-- メッセージログ全体 -->
<div
role="log"
aria-label="チャット履歴"
aria-live="polite"
aria-relevant="additions"
>
<!-- ユーザーメッセージ -->
<div role="article" aria-label="あなた">
<p>Carouselをいつ使うべきか教えてください。</p>
</div>
<!-- AI応答 -->
<div role="article" aria-label="AIアシスタント">
<p>Carouselは以下の場面で有効です…</p>
</div>
</div>
<!-- 入力欄 -->
<textarea
aria-label="メッセージ入力"
aria-describedby="input-hint"
/>
<p id="input-hint">Enter で送信、Shift+Enter で改行</p>
<!-- ストリーミング中の送信ボタン切り替え -->
<button aria-label="生成を停止">■</button>
10. 実装メモ(Implementation Notes)
- Vercel AI SDK:
useChatフックがストリーミング・メッセージ管理・エラー状態・中断(stop())をすべてカバーしており、AI Chat UIを構築する場合の第一候補 - ストリーミング実装:OpenAI APIの
stream: true+ReadableStreamで逐次受信し、setStreamingText(prev => prev + chunk)で追記するパターンが基本 - Markdown レンダリング:AI応答にMarkdownが含まれる場合は
react-markdown+remark-gfmで安全にレンダリングする。dangerouslySetInnerHTMLは使用しない - メッセージの永続化:会話履歴を
localStorageまたは DB に保存する場合、messagesstateを永続化するロジックをuseEffectで実装する
11. 関連リンク
- 関連するUIデザイン原則: フィードバック (Feedback), システム状態の可視性 (Visibility of System Status)
- 用語集(定義): アクセシビリティ
- 関連するUIコンポーネント(横): Loading(ローディング), Spinner(スピナー), Scroll Area(スクロールエリア), Text Input(テキスト入力), Sheet / Drawer(ドロワー / シート)
12. まとめ
AI Chat UIの設計で最重要なのは「ストリーミング中の状態管理」と「中断ボタンの提供」です。AIの応答はユーザーの期待と一致しないことも多く、途中で止めたいニーズは頻繁に発生します。role="log" + aria-live="polite" のアクセシビリティ実装と、エラー時のインライン再試行UIは必須実装です。実装コストを下げるためには Vercel AI SDK の useChat フックを活用することを強く推奨します。