訊息輸入區 (Chat Composer)
- 新提案
- →
- 封閉測試
- →
- 公開測試
- →
- 已穩定
成熟度說明
- 新提案:未完成開發、請勿使用。
- 封閉測試:開發暫時性完成,可使用。可能仍有親和力或其他使用上問題待透過實測發現。
- 公開測試:開發暫時性完成,歡迎使用。具有完整親和力報告。
- 已穩定:開發完成、歡迎使用。應無任何親和力或使用上問題。
基本範例
與客服助理的對話
測試送出狀態
開啟後,此範例的每次送出都會失敗並保留輸入內容;再次按下可關閉。
HTML
<form class="chat-composer" data-chat-composer action="/messages" method="post">
<label class="chat-composer__label" for="chat-message">訊息</label>
<p id="chat-message-hint" class="chat-composer__hint">Enter 換行,Ctrl+Enter 或 Command+Enter 送出。</p>
<textarea
id="chat-message"
class="chat-composer__input"
name="message"
rows="3"
required
aria-describedby="chat-message-hint chat-message-error"
data-chat-composer-input
></textarea>
<p id="chat-message-error" class="chat-composer__error" data-chat-composer-error hidden></p>
<p class="chat-composer__status" data-chat-composer-status hidden></p>
<div class="chat-composer__actions">
<button class="button button-primary" type="submit" data-chat-composer-submit>送出訊息</button>
</div>
</form>- Enter/Shift+Enter 換行;Ctrl+Enter 或 Command+Enter 送出。
- 「測試送出狀態」可持續模擬失敗;它與回覆期間的停止按鈕只供組合示範,不屬於元件。
附加檔案(選用)
附加檔案給客服助理
測試送出狀態
開啟後,此範例的每次送出都會失敗並保留輸入內容;再次按下可關閉。
HTML
<form class="chat-composer" data-chat-composer action="/messages" method="post" enctype="multipart/form-data">
<label class="chat-composer__label" for="chat-message-with-files">訊息</label>
<p id="chat-message-with-files-hint" class="chat-composer__hint">
Enter 換行,Ctrl+Enter 或 Command+Enter 送出。
</p>
<textarea
id="chat-message-with-files"
class="chat-composer__input"
name="message"
rows="3"
required
aria-describedby="chat-message-with-files-hint chat-message-with-files-error"
data-chat-composer-input
></textarea>
<div class="chat-composer__selection" data-chat-composer-selection hidden>
<ul class="file-upload__file-list" aria-label="已選擇的檔案" data-chat-composer-attachment-list></ul>
<button class="button" type="button" data-chat-composer-clear-attachments>清除全部附件</button>
</div>
<p id="chat-message-with-files-error" class="chat-composer__error" data-chat-composer-error hidden></p>
<p class="chat-composer__status" data-chat-composer-status hidden></p>
<div class="chat-composer__actions">
<div class="chat-composer__attachments">
<label class="visually-hidden" for="chat-attachments">附加檔案</label>
<p id="chat-attachments-hint" class="visually-hidden">
可一次附加多個檔案。
</p>
<div class="file-upload file-upload--compact">
<input
id="chat-attachments"
class="file-upload__input"
type="file"
name="attachments"
multiple
aria-describedby="chat-attachments-hint"
data-chat-composer-attachments
>
<div class="file-upload__dropzone" aria-hidden="true">
<span class="file-upload__button">附加檔案</span>
</div>
</div>
</div>
<button class="button button-primary" type="submit" data-chat-composer-submit>送出訊息</button>
</div>
</form>- 附件功能可以省略;需要時,使用檔案上傳的 compact 樣式與
data-chat-composer-attachments,放在輸入區操作列。 - 元件只列出檔名與清除按鈕;
accept、multiple、數量、大小、上傳與安全檢查由採用端設定。
使用方式
採用端監聽原生 submit,取得送出當下的提交快照(snapshot),並在後端結果確定後呼叫控制器:
const form = document.querySelector('[data-chat-composer]');
form.addEventListener('submit', async (event) => {
event.preventDefault();
const formData = new FormData(form);
const submission = form.chatComposer.captureSubmission();
form.chatComposer.setBusy(true);
try {
await sendMessage(formData);
form.chatComposer.accept(submission);
} catch (error) {
form.chatComposer.fail('訊息未送出,輸入內容已保留,請稍後再試。');
}
});| 方法 | 用途 |
|---|---|
captureSubmission() | 記錄送出當下的狀態;資料仍由 FormData 取得 |
accept(submission) | 接受請求、進入忙碌;若有狀態節點則顯示「訊息已送出,正在等待回覆」,並清除未被修改的草稿與附件 |
fail(message) | 送出失敗時保留內容、顯示錯誤,並依焦點位置提供一次回饋 |
setBusy(isBusy) | 控制是否允許再次送出 |
setStatus(message) | 更新可見操作狀態;傳入空字串時隱藏 |
clearError() | 清除錯誤,不改變草稿或焦點 |
串流開始後的錯誤由訊息氣泡處理;不要再呼叫 Composer 的 fail()。使用者訊息請透過對話容器加入紀錄。
CSS
.chat-composer/.chat-composer__input:表單與多行訊息欄位。.chat-composer__error/.chat-composer__status:錯誤與操作狀態。.chat-composer__attachments/.chat-composer__actions:操作列中的選用附件與送出控制。
親和力
- 保留可見 label 與原生 required 驗證;placeholder 不取代 label。
- 空白或忙碌時以
aria-disabled表達狀態,送出按鈕仍保留在 Tab 順序中。 - 元件不移動焦點或建立額外的 live region。焦點留在輸入框時,由既有的
aria-describedby錯誤關聯提供回饋;焦點位於其他控制時,才使用頁面既有的<live-announcer>播報,避免同一句錯誤重複朗讀。 - 組合串流 Message Bubble 時,對話紀錄設定
aria-live="off",避免它與<live-announcer>重複播報 AI 回覆。
JavaScript
元件以 ES module 撰寫,載入必須加 type="module"。跨網域載入時,伺服器必須提供 CORS 標頭。
<script type="module" src="js/components/chat-composer.js"></script>- 腳本載入時自動初始化所有
[data-chat-composer];不處理載入後才動態插入的表單。 - 表單必須包含
[data-chat-composer-input]、[data-chat-composer-submit]與[data-chat-composer-error];缺少任一節點時不會初始化。狀態與附件相關節點皆為選用。 - 使用
fail()且焦點不在輸入框時,頁面必須掛載一個<live-announcer>並載入其腳本;缺少時仍會顯示持久錯誤,但不會額外動態播報。 - 無 JS 時,原生 form action、required textarea 與 submit button 仍可使用;採用端必須提供有效的
action。
參考
- The textarea element - WHATWG
- KeyboardEvent.isComposing - W3C UI Events
- Making Disabled Buttons More Inclusive - Sandrina Pereira