AI 應用元件
生成挑選流程
輸入提示詞後先顯示骨架,再讓一排生成結果橫向滑入,使用者挑選其中一張放大確認,是圖像與影片生成產品的標準流程。
圖像與影片生成產品最常見的一段流程:打字 → 生成 → 一排選項滑過 → 選一個。元件把它做成四段狀態機(idle、generating、results、picked):輸入列有自動長高的多行提示詞、比例與張數 chip;生成中依比例顯示骨架卡與斜向 shimmer;結果回來後逐張取代骨架、從右側滑入,整列可橫向捲動;點任一張就以共享 layout 動畫放大到上方預覽,下方提供「使用這張」「重新生成」「變化」。生成邏輯完全由你的 onGenerate 提供。
把這個效果裝進你的專案
在專案資料夾執行指令,CLI 會加入原始碼與依賴套件,再依下方使用範例引用元件。
npx webberui@latest add "https://webberui.com/r/generate-and-pick-flow.json?t=<安裝 token>"Playground
即時調整 props、程式碼片段同步更新——直接試出你要的樣子再複製。
4
80
編輯中的呼叫預設屬性
<GenerateAndPickFlow/>
完整範例包含預覽的排版與資料。先安裝元件,再把範例檔貼入你的專案。
安裝
npx webberui@latest add "https://webberui.com/r/generate-and-pick-flow.json?t=<安裝 token>"或在 components.json 設定 registries 後,改用 @webberui/generate-and-pick-flow 安裝。
使用
import {
GenerateAndPickFlow,
type GenerateAndPickFlowResult,
} from "@/components/ui/generate-and-pick-flow";
async function generate(
prompt: string,
options: { ratio: string; count: number },
): Promise<GenerateAndPickFlowResult[]> {
const res = await fetch("/api/generate", {
method: "POST",
body: JSON.stringify({ prompt, ...options }),
});
const images: { id: string; url: string }[] = await res.json();
return images.map((img, i) => ({
id: img.id,
title: `版本 ${i + 1}`,
preview: <img src={img.url} alt="" className="object-cover" />,
}));
}
<GenerateAndPickFlow
defaultPrompt="黃昏海邊的紙飛機,水彩風格"
onGenerate={generate}
onPick={(result) => console.log("採用", result.id)}
/>;Props
| Prop | 型別 | 預設值 | 說明 |
|---|---|---|---|
onGenerate | (prompt: string, options: GenerateAndPickFlowOptions) => Promise<GenerateAndPickFlowResult[]> | — | 生成函式;reject 時顯示錯誤卡與重試鈕 |
onPick | (result: GenerateAndPickFlowResult) => void | — | 在放大預覽按「使用這張」時回呼 |
defaultPrompt | string | "" | 提示詞的初始內容 |
placeholder | string | "描述你想生成的畫面…" | 提示詞的佔位文字 |
ratios | string[] | ["1:1", "16:9", "9:16"] | 比例 chip,第一個為預設 |
count | number | — | 受控的生成張數(2–6) |
defaultCount | number | 4 | 非受控模式的初始張數 |
onCountChange | (count: number) => void | — | 張數變動時回呼 |
status | "idle" | "generating" | "results" | "picked" | — | 受控的狀態機階段;未提供時由元件內部管理 |
onStatusChange | (status: GenerateAndPickFlowStatus) => void | — | 階段變動時回呼 |
shimmer | boolean | true | 骨架卡是否顯示斜向 shimmer |
accent | string | — | 選中外框的強調色;未提供時使用 --wb-generate-pick-accent |
stagger | number | — | 結果逐張滑入的間隔(毫秒);未提供時讀取 --wb-generate-pick-stagger |
className | string | — | 透傳到最外層容器 |
GenerateAndPickFlowResult
| 欄位 | 型別 | 預設值 | 說明 |
|---|---|---|---|
id | string | — | 唯一識別碼,用於 layout 動畫與焦點還原 |
preview | ReactNode | — | 預覽內容,會填滿依比例裁切的卡片 |
title | string | — | 標題,顯示於放大預覽下方並作為卡片的無障礙名稱 |
GenerateAndPickFlowOptions
| 欄位 | 型別 | 預設值 | 說明 |
|---|---|---|---|
ratio | string | — | 目前選擇的比例 |
count | number | — | 要生成的張數 |
variationOf | GenerateAndPickFlowResult | — | 按「變化」時帶入被變化的那張;一般生成為 undefined |
細節
- CSS 變數:
--wb-generate-pick-shimmer(預設1.4s)控制 shimmer 一輪的時長,--wb-generate-pick-stagger(預設80ms)控制結果逐張出現的間隔,--wb-generate-pick-accent(預設#8b5cf6)是選中外框色。accent、staggerprop 有值時會覆寫對應變數 - 逐張揭露:Promise 回來後,骨架依 stagger 間隔一張張換成結果,每張從 x 60px、透明度 0 以彈簧(stiffness 300、damping 30)滑入
- 放大預覽:被點的卡以共享 layoutId 飛到上方(stiffness 260、damping 28),原位留下同尺寸的「已選取」外框,其他卡縮小變暗;Esc 返回
- 橫向捲動:結果列使用 scroll-snap,滑鼠滾輪會轉成橫向捲動,捲到盡頭時放行給頁面
- 防錯置:連按生成時只採用最後一次呼叫的結果,較早回來的 Promise 會被丟棄
- 變化:「變化」會以同一提示詞再次呼叫
onGenerate,並在options.variationOf帶入被變化的那張
可及性
- 提示詞輸入框按 Enter 送出、Shift+Enter 換行;中文等 IME 組字中的 Enter 不會送出
- 結果列為
role="listbox"、每張卡為role="option"並帶aria-selected;左右方向鍵、Home/End 移動焦點,Enter 或空白鍵選取 - 生成中結果列帶
aria-busy,aria-live區域宣告「正在生成 N 張」與「已生成 N 張」,失敗時以role="alert"顯示錯誤與重試鈕 - 選取後焦點移到「使用這張」,按 Esc 返回結果列並把焦點還給原卡片
- 使用者系統開啟「減少動態效果」時,骨架不顯示 shimmer、結果直接出現,選取時直接切換、不做 layout 飛行動畫