輸入元件
NPS 淨推薦值調查卡
NPS 調查卡 React 元件:0–10 分段按鈕依貶損/被動/推薦者著色,選分後展開對應追問欄,送出切換感謝態,並附 npsCategory 與 npsScore 計算函式。
SaaS 常見的滿意度調查題型。0–10 十一顆分數按鈕依 NPS 慣例分成三個區間——0–6 貶損者(紅)、7–8 被動者(琥珀)、9–10 推薦者(綠)——選中後同區間整組淡染、選中那顆彈跳;下方展開依分數變化的追問輸入欄(低分問哪裡失望、高分問最喜歡哪一點),送出後整卡切換為打勾感謝態。另外匯出 npsCategory 與 npsScore 兩個純函式,讓你在後台用同一套規則把回收的分數換算成 NPS。
把這個效果裝進你的專案
在專案資料夾執行指令,CLI 會加入原始碼與依賴套件,再依下方使用範例引用元件。
npx webberui@latest add nps-survey-cardPlayground
即時調整 props、程式碼片段同步更新——直接試出你要的樣子再複製。
編輯中的呼叫預設屬性
<NpsSurveyCard/>
完整範例包含預覽的排版與資料。先安裝元件,再把範例檔貼入你的專案。
安裝
npx webberui@latest add https://webberui.com/r/nps-survey-card.json或在 components.json 設定 registries 後,改用 @webberui/nps-survey-card 安裝。
使用
import { NpsSurveyCard, npsScore } from "@/components/ui/nps-survey-card";
<NpsSurveyCard
onChange={(score) => console.log("選分", score)}
onSubmit={({ score, comment }) => console.log(score, comment)}
requireComment
/>
// 分數計算可單獨使用:推薦者% − 貶損者%,回傳 -100~100 的整數
npsScore([10, 9, 8, 6, 3]); // 40 − 40 = 0Props
| Prop | 型別 | 預設值 | 說明 |
|---|---|---|---|
value | number | null | — | 受控選中分數(0–10);null 表示尚未選分,不提供此 prop 時為非受控模式 |
defaultValue | number | null | null | 非受控模式的初始分數 |
onChange | (score: number) => void | — | 選分時回呼(點擊、鍵盤方向鍵與數字鍵都會觸發) |
onSubmit | (result: { score: number; comment: string }) => void | — | 按下送出時回呼,附分數與追問回覆(去除前後空白) |
onReset | () => void | — | 提供時感謝態會顯示「再填一次」按鈕,按下後重置內部狀態並回呼 |
question | string | "你有多可能把我們推薦給朋友或同事?" | 主問題文字 |
followUpQuestion | string | — | 追問文字模板,模板中的 {score} 會代入實際分數;提供時優先於 followUps 與內建預設 |
followUps | Partial<Record<NpsCategory, string>> | — | 依類別覆寫追問文字(detractor/passive/promoter),同樣支援 {score} 佔位 |
showLabels | boolean | true | 顯示兩端「完全不可能/非常可能」標籤 |
requireComment | boolean | false | 追問必填:留言為空時送出按鈕停用 |
compact | boolean | false | 緊湊模式:縮小按鈕、字級與間距 |
labels | Partial<NpsSurveyCardLabels> | — | 覆寫介面文案 |
className | string | — | 透傳到最外層卡片 |
NpsSurveyCardLabels
| 欄位 | 型別 | 預設值 | 說明 |
|---|---|---|---|
low | string | "完全不可能" | 0 分端的標籤文字 |
high | string | "非常可能" | 10 分端的標籤文字 |
detractor | string | "貶損者" | 0–6 分的類別名稱(無障礙播報用) |
passive | string | "被動者" | 7–8 分的類別名稱 |
promoter | string | "推薦者" | 9–10 分的類別名稱 |
commentPlaceholder | string | "想到什麼都可以寫" | 追問輸入框的 placeholder |
commentRequired | string | "此欄為必填,寫幾個字就可以" | requireComment 時顯示的必填提示 |
submit | string | "送出" | 送出按鈕文字 |
thanksTitle | string | "感謝你的回饋!" | 感謝態標題 |
thanksBody | string | "我們會認真閱讀每一則意見。" | 感謝態說明文字 |
reset | string | "再填一次" | 「再填一次」按鈕文字(需提供 onReset 才會顯示) |
另外具名匯出 npsCategory(score)(把 0–10 分歸類為 "detractor" | "passive" | "promoter")、npsScore(scores)(推薦者百分比減貶損者百分比,四捨五入為整數;空陣列回傳 0)與 NpsCategory、NpsSurveyCardLabels 型別,方便在後台沿用同一套計分規則。
細節
- 追問文字的決定順序:
followUpQuestion(模板中{score}會代入實際分數)優先,其次followUps依類別覆寫,最後才是內建預設——低分問「我們哪裡讓你失望了?」、中分問「還差什麼就能讓你打更高分?」、高分問「最喜歡哪一點?」 - 追問欄的 Enter 只會換行、不會送出,送出一律透過按鈕——避免打字到一半誤送
- 窄容器時 11 顆按鈕以 flex-wrap 自動換行成兩排,不需要額外設定
- 感謝態的「再填一次」只在提供
onReset時顯示;受控模式下請在onReset回呼裡把value設回null
可及性
- 0–10 分數按鈕組為
role="radiogroup"(以主問題aria-labelledby命名),每顆分數為role="radio"搭配aria-checked,並採 roving tabindex——Tab 進入群組後以 ←/→(或數字鍵、Home/End)移動選取 - 選分後以
aria-live="polite"區域播報分數與所屬類別(貶損者/被動者/推薦者),送出後播報感謝訊息 - 追問輸入框以
label關聯追問文字;requireComment時同步設定aria-required並以aria-describedby連到必填提示 - 使用者系統開啟「減少動態效果」時,停用選中彈跳、hover 抬升、展開與打勾動畫,狀態直接切換