AI 應用元件
腳本式對話展示
依腳本自動播放的對話展示 React 元件:使用者氣泡 spring 彈入、三點打字指示、助理逐字串流回覆與程式碼區塊,可循環。
把一段寫好的對話腳本變成會自己播放的聊天畫面,適合放在產品首頁、功能介紹或客服流程說明。使用者訊息從右下以 spring 彈入並帶輕微 overshoot;助理回覆前先出現三點打字指示,接著氣泡從左彈入、文字逐字串流,附帶的程式碼區塊則逐行出現並帶行號與複製按鈕。進入視口才開始播放,有新內容時自動捲到底;開啟 loop 會在播完後淡出清空、從頭再來。可選 frame="phone" 包進簡化的 CSS 手機殼。
把這個效果裝進你的專案
在專案資料夾執行指令,CLI 會加入原始碼與依賴套件,再依下方使用範例引用元件。
npx webberui@latest add scripted-chat-threadPlayground
即時調整 props、程式碼片段同步更新——直接試出你要的樣子再複製。
22
400
編輯中的呼叫預設屬性
<ScriptedChatThread/>
完整範例包含預覽的排版與資料。先安裝元件,再把範例檔貼入你的專案。
安裝
npx webberui@latest add https://webberui.com/r/scripted-chat-thread.json或在 components.json 設定 registries 後,改用 @webberui/scripted-chat-thread 安裝。
使用
import { ScriptedChatThread } from "@/components/ui/scripted-chat-thread";
<ScriptedChatThread
frame="phone"
loop
messages={[
{ role: "user", content: "我的訂單三天了還沒出貨" },
{ role: "assistant", content: "抱歉讓你久等了!方便提供訂單編號嗎?" },
{ role: "user", content: "#BK20261025" },
{
role: "assistant",
typingMs: 1200,
content: "已完成揀貨,預計明天出貨。查詢範例:",
code: {
lang: "ts",
text: 'const res = await fetch("https://api.example.com/v1/orders/BK20261025");',
},
},
]}
onComplete={() => console.log("播放完成")}
/>需要手動控制播放時,傳入 ref 取得 restart():
const threadRef = React.useRef<ScriptedChatThreadHandle>(null);
<ScriptedChatThread ref={threadRef} autoplay={false} messages={script} />
<button onClick={() => threadRef.current?.restart()}>重新播放</button>Props
| Prop | 型別 | 預設值 | 說明 |
|---|---|---|---|
messages | ScriptedChatMessage[] | — | 依序播放的對話腳本 |
autoplay | boolean | true | 是否自動播放;true 時進入視口才開始,false 時顯示播放鈕或等 ref.restart() |
loop | boolean | false | 播完後停 2500ms、淡出清空並從頭重播 |
charMs | number | 22 | 助理文字每字的毫秒數;未提供時讀取 CSS 變數 --wb-sct-char-ms,再退回 22 |
gapMs | number | 600 | 訊息與訊息之間的間隔毫秒數 |
springConfig | ScriptedChatSpring | { stiffness: 400, damping: 28 } | 氣泡進場的 spring 參數 |
frame | "none" | "phone" | "none" | 外框:none 為一般卡片,phone 包在簡化的 CSS 手機殼內 |
height | number | string | 440 | 對話捲動區的高度(數字為 px) |
avatar | React.ReactNode | 圓形字母「助」 | 助理頭像;預設為強調色圓形字母 |
ariaLabel | string | "對話示範" | 容器的無障礙名稱 |
onComplete | () => void | — | 整段腳本播放完成時回呼(loop 時每輪觸發一次) |
ref | React.Ref<ScriptedChatThreadHandle> | — | 命令式 API,提供 restart() |
className | string | — | 透傳到最外層容器 |
ScriptedChatMessage
| 欄位 | 型別 | 預設值 | 說明 |
|---|---|---|---|
id | string | 索引 | 訊息識別碼,用作 React key |
role | "user" | "assistant" | — | 發話者:user 靠右、assistant 靠左並帶頭像 |
content | string | — | 文字內容;assistant 會逐字串流 |
code | ScriptedChatCode | — | 程式碼區塊;接在文字之後逐行串流 |
typingMs | number | 900 | assistant 回覆前顯示打字指示的毫秒數 |
ScriptedChatCode
| 欄位 | 型別 | 預設值 | 說明 |
|---|---|---|---|
lang | string | — | 語言標籤,顯示於區塊左上角 |
text | string | — | 程式碼原文,以換行分行 |
ScriptedChatSpring
| 欄位 | 型別 | 預設值 | 說明 |
|---|---|---|---|
stiffness | number | 400 | 彈性係數,越大越快越彈 |
damping | number | 28 | 阻尼,越小 overshoot 越明顯 |
ScriptedChatThreadHandle
| 欄位 | 型別 | 預設值 | 說明 |
|---|---|---|---|
restart | () => void | — | 清空並從第一則訊息重新播放 |
細節
- 播放節奏:使用者氣泡彈入後停 400ms;助理先顯示打字指示
typingMs,再逐字串流(每字charMs),程式碼以逐行串流(每行charMs× 8);每則訊息之間間隔gapMs。 - 自動捲底:只有使用者原本就在底部(距底小於 24px)時才會跟著捲;往上捲會暫停跟隨並顯示「回到最新」小按鈕,按下即回到底部繼續跟隨。
messages以內容比對,寫成 inline 陣列也不會因父層重新渲染而重播。- CSS 變數:
--wb-sct-char-ms設定預設逐字速度(charMsprop 優先),--wb-sct-accent設定頭像與游標的強調色。 - 可以把本元件放進
chat-scroller內組合使用,但兩者互不依賴;本元件自己就有捲底與「回到最新」行為。
可及性
- 捲動容器為
role="log"、aria-live="polite",以ariaLabel(預設「對話示範」)命名 - 串流中的部分文字對輔助科技隱藏;訊息完成後才把完整文字(含發話者)放進可讀節點,避免螢幕閱讀器逐字朗讀
- 打字指示帶 sr-only「正在輸入」;程式碼的複製按鈕與「回到最新」、「播放對話」皆為
type="button",有可見的 focus 外框 - 使用者系統開啟「減少動態效果」時,不彈入、不串流、不顯示打字指示,所有訊息以 150ms 淡入直接全部出現,
onComplete立即觸發