AI 應用元件
追問建議膠囊
AI 建議提問列 React 元件:回覆下方的膠囊逐一錯開進場,點擊後膠囊沿弧線飛進輸入框並化為文字,其餘膠囊收合退場;支援換行或單行捲動、鍵盤方向鍵切換與 IME 保護。
AI 對話回覆下方常見的「你可能想問」建議列。膠囊依序錯開淡入;點擊其中一顆時,元件在 body 建立一個複本,沿著略往上拱的弧線飛到輸入框的文字落點,途中外框與背景淡去、只剩文字,抵達後把文字寫入輸入框、聚焦並閃一下外框 ring,其餘膠囊同時收合退場。換成新的一組 suggestions 時會自動重播進場。沒有提供 targetRef 時,只保留按壓回饋與收合,直接呼叫 onSelect。
把這個效果裝進你的專案
在專案資料夾執行指令,CLI 會加入原始碼與依賴套件,再依下方使用範例引用元件。
npx webberui@latest add follow-up-suggestion-chipsPlayground
即時調整 props、程式碼片段同步更新——直接試出你要的樣子再複製。
40
420
編輯中的呼叫預設屬性
<FollowUpSuggestionChips/>
完整範例包含預覽的排版與資料。先安裝元件,再把範例檔貼入你的專案。
安裝
npx webberui@latest add https://webberui.com/r/follow-up-suggestion-chips.json或在 components.json 設定 registries 後,改用 @webberui/follow-up-suggestion-chips 安裝。
使用
import * as React from "react";
import { FollowUpSuggestionChips } from "@/components/ui/follow-up-suggestion-chips";
export function ChatFooter() {
const inputRef = React.useRef<HTMLInputElement>(null);
const [value, setValue] = React.useState("");
return (
<>
<FollowUpSuggestionChips
suggestions={["週三要帶什麼?", "推薦室內景點", "改查台中"]}
targetRef={inputRef}
onSelect={(text) => setValue(text)}
/>
<input
ref={inputRef}
value={value}
onChange={(e) => setValue(e.target.value)}
/>
</>
);
}Props
| Prop | 型別 | 預設值 | 說明 |
|---|---|---|---|
suggestions | Array<string | FollowUpSuggestion> | — | 建議提問清單;換成新的一組時會重新錯開進場 |
onSelect | (value: string, detail: FollowUpSuggestionSelectDetail) => void | — | 選取建議時回呼;有 targetRef 時在飛入動畫結束、文字寫入後才呼叫 |
targetRef | React.RefObject<HTMLInputElement | HTMLTextAreaElement | null> | — | 飛行目的地的輸入框;提供時啟用飛入動畫,結束後寫入文字並聚焦 |
mode | "fill" | "send" | "fill" | fill 只填入;send 由父層在 onSelect 直接送出(元件只透過 detail.mode 告知) |
layout | "wrap" | "scroll" | "wrap" | wrap 自動換行;scroll 單行水平捲動並加兩端漸層遮罩 |
stagger | number | 40 | 每顆膠囊進場的錯開間隔(毫秒) |
duration | number | 220 | 單顆膠囊進場與收合的時長(毫秒),同時寫入 --wb-follow-up-suggestion-chips-duration |
flightDuration | number | 420 | 膠囊飛進輸入框的時長(毫秒);0 表示不飛行、直接填入 |
hideOnSelect | boolean | true | 選取後其餘膠囊是否收合退場 |
label | string | "你可能想問" | 列前方的小字標籤,同時作為群組的 aria-label;傳空字串可隱藏 |
disabled | boolean | false | 停用所有膠囊 |
className | string | — | 透傳到最外層容器 |
FollowUpSuggestion
| 欄位 | 型別 | 預設值 | 說明 |
|---|---|---|---|
id | string | — | 唯一識別碼,用於 React key 與選取狀態 |
label | string | — | 膠囊上顯示的文字 |
value | string | label | 實際填入輸入框的文字 |
icon | React.ReactNode | — | 膠囊左側的小圖示 |
FollowUpSuggestionSelectDetail
| 欄位 | 型別 | 預設值 | 說明 |
|---|---|---|---|
suggestion | FollowUpSuggestion | — | 被選取的建議(字串會規格化成物件) |
mode | "fill" | "send" | — | 目前的 mode,父層據此決定是否直接送出 |
index | number | — | 被選取的建議在 suggestions 中的索引 |
細節
- 落點量測:取輸入框內文起點(左緣 + 邊框 +
padding-left),垂直置中;輸入框已有文字時,以一個複製字型樣式的隱藏 span 量出文字寬度,落在文字結尾附近(夾在輸入框可視範圍內)。textarea會落在最後一行。 - 寫入文字:透過原生
valuesetter 寫入並派送input事件,受控輸入框的onChange也會收到新值;同時呼叫onSelect,父層照常setValue即可,兩條路徑結果一致。 - 飛行複本以
createPortal掛在 body、position: fixed,原膠囊改為visibility: hidden佔位,因此列的版面在飛行期間不會跳動。 - 節奏變數:
--wb-follow-up-suggestion-chips-duration(hover 色彩過渡,等於duration)、--wb-follow-up-suggestion-chips-ease(預設cubic-bezier(0.23,1,0.32,1))、--wb-follow-up-suggestion-chips-ring(落地時輸入框外框閃光的顏色)。 - 傳入新的
suggestions(id 組合不同)會重置選取與收合狀態,並重播錯開進場。
可及性
- 列容器為
role="group",以label作為aria-label;每顆膠囊都是type="button"的原生按鈕 - 鍵盤:Tab 進入列後以 ←/→ 在膠囊間移動焦點(roving tabindex),Home/End 跳到頭尾,Enter/Space 選取;keydown 開頭有 IME 組字保護
- 選取後焦點移到
targetRef輸入框並把游標放到結尾;aria-live="polite"區域宣告「已填入:…」 - 使用者系統開啟「減少動態效果」時,不飛行、不錯開,膠囊直接淡出並立即填入文字