Multi-step Form
多步驟表單容器,方向感知的滑動過場搭配可切換款式的進度指示。
載入預覽⋯
Playground
即時調整 props、程式碼片段同步更新——直接試出你要的樣子再複製。
<MultiStepForm />
安裝
npx shadcn@latest add https://webberui.com/r/multi-step-form.json或在 components.json 設定 registries 後,改用 @webberui/multi-step-form 安裝。
安裝依賴後,從 registry JSON(/r/multi-step-form.json 的 files[0].content)複製 multi-step-form.tsx 原始碼到你的 components/ui/ 目錄:
npm install motion lucide-react clsx tailwind-merge使用
以 <MultiStepFormStep> 宣告每一個步驟,容器會依目前步驟做方向感知的滑動過場,並自動渲染進度指示與上一步/下一步控制列。
import {
MultiStepForm,
MultiStepFormStep,
} from "@/components/ui/multi-step-form";
<MultiStepForm variant="steps" onComplete={() => console.log("done")}>
<MultiStepFormStep label="帳號">{/* ...欄位 */}</MultiStepFormStep>
<MultiStepFormStep label="個人資料">{/* ...欄位 */}</MultiStepFormStep>
<MultiStepFormStep label="確認">{/* ...摘要 */}</MultiStepFormStep>
</MultiStepForm>;自訂控制列
將 controls 設為 false,改用 useMultiStepForm() hook 在任意位置自組導覽(可加入驗證後才 next()):
import { useMultiStepForm } from "@/components/ui/multi-step-form";
function Footer() {
const { back, next, isFirst, isLast } = useMultiStepForm();
return (
<div>
<button onClick={back} disabled={isFirst}>
上一步
</button>
<button onClick={next}>{isLast ? "送出" : "下一步"}</button>
</div>
);
}受控模式
傳入 step 與 onStepChange 即可完全掌控目前步驟,適合搭配表單驗證做步驟守門。
const [step, setStep] = React.useState(0);
<MultiStepForm step={step} onStepChange={(next) => setStep(next)}>
{/* ...steps */}
</MultiStepForm>;Props
MultiStepForm
| Prop | 型別 | 預設值 | 說明 |
|---|---|---|---|
children | ReactNode | — | 步驟宣告,皆為 <MultiStepFormStep> |
step | number | — | 受控目前步驟索引;不傳則為非受控 |
defaultStep | number | 0 | 非受控模式的初始步驟索引 |
onStepChange | (step: number, direction: 1 | -1) => void | — | 步驟變更時觸發,帶入新索引與方向 |
onComplete | () => void | — | 於最後一步按下「完成」時觸發 |
variant | "bar" | "dots" | "steps" | false | "steps" | 進度指示款式;false 不顯示 |
controls | boolean | true | 是否渲染內建控制列 |
backLabel | string | "上一步" | 上一步按鈕文字 |
nextLabel | string | "下一步" | 下一步按鈕文字 |
completeLabel | string | "完成" | 末步按鈕文字 |
MultiStepFormStep
| Prop | 型別 | 預設值 | 說明 |
|---|---|---|---|
label | string | — | 進度指示顯示的步驟標題 |
children | ReactNode | — | 步驟內容 |
className | string | — | 追加到步驟容器的 className |
useMultiStepForm()
回傳 { step, total, direction, isFirst, isLast, goTo, next, back, reducedMotion },供自訂控制列或進度指示使用。
細節
- 三種進度款式:
bar進度條、dots圓點(目前點延伸為膠囊)、steps編號步驟(完成打勾、連接線依進度上色)。 - 方向感知:前進時新步驟自右側滑入、舊步驟往左退場;後退則相反。方向於 render 期間依前次索引推導,受控與非受控皆正確。
- 檢視區採
overflow-hidden裁切水平滑動,並以popLayout讓退場步驟脫離流排、由進場步驟決定容器高度,避免過場時高度塌陷。
可及性
- 進度指示中「目前與先前」的步驟可點擊回跳(
goTo),未到達的步驟停用,維持填寫順序。 - 目前步驟標上
aria-current="step";進度條提供role="progressbar"與aria-valuenow。 - 步驟切換透過
aria-live="polite"區塊朗讀「步驟 x / y」。 - 內建控制列為原生
button,可鍵盤操作並具focus-visible外框;第一步時上一步鈕停用。 - 使用者系統開啟「減少動態效果」時,滑動退化為短暫淡入淡出,進度填充直接跳位。