輸入元件
單選群組
單選群組 React 元件:選中圓點以彈簧放大,卡片變體的選中外框在選項間滑動,方向鍵切換也同樣滑動;支援受控/非受控、直橫排列與表單送出。
資料驅動的單選群組:傳入 options 陣列即可,每項可帶標籤、說明、停用狀態,卡片變體還能在右上角放價格等附加資訊。dot 變體選中時內圓以彈簧放大;card 變體的選中外框是一個獨立元素,以 layoutId 在卡片之間滑動——滑鼠點擊與方向鍵切換都一樣。鍵盤操作自己實作 roving tabindex,行為與原生 radio 一致,不依賴任何 headless 套件。
把這個效果裝進你的專案
在專案資料夾執行指令,CLI 會加入原始碼與依賴套件,再依下方使用範例引用元件。
npx webberui@latest add radio-groupPlayground
即時調整 props、程式碼片段同步更新——直接試出你要的樣子再複製。
500
30
編輯中的呼叫預設屬性
<RadioGroup/>
完整範例包含預覽的排版與資料。先安裝元件,再把範例檔貼入你的專案。
安裝
npx webberui@latest add https://webberui.com/r/radio-group.json或在 components.json 設定 registries 後,改用 @webberui/radio-group 安裝。
使用
import { RadioGroup } from "@/components/ui/radio-group";
<RadioGroup
variant="card"
aria-label="方案"
name="plan"
defaultValue="pro"
options={[
{ value: "starter", label: "入門版", description: "3 個專案", meta: "NT$0/月" },
{ value: "pro", label: "專業版", description: "無限專案與版本紀錄", meta: "NT$290/月" },
{ value: "team", label: "團隊版", description: "成員管理與單一登入", meta: "NT$890/月" },
]}
onValueChange={(value) => console.log(value)}
/>Props
| Prop | 型別 | 預設值 | 說明 |
|---|---|---|---|
options | RadioGroupOption[] | — | 選項清單(資料驅動) |
value | string | — | 受控的選中值;未提供時由元件內部管理(非受控) |
defaultValue | string | — | 非受控模式的初始選中值 |
onValueChange | (value: string) => void | — | 選中值變動時回呼,參數為新選中的值 |
orientation | "vertical" | "horizontal" | "vertical" | 排列方向,同時決定 aria-orientation |
variant | "dot" | "card" | "dot" | 外觀變體 |
stiffness | number | 500 | 彈簧剛性(圓點放大與外框滑動共用) |
damping | number | 30 | 彈簧阻尼(圓點放大與外框滑動共用) |
name | string | — | 表單欄位名稱;提供時渲染一個 hidden input 讓表單可送出選中值 |
disabled | boolean | false | 停用整組 |
aria-label | string | — | 群組的無障礙名稱(沒有可見標題時使用) |
aria-labelledby | string | — | 指向可見標題元素的 id,作為群組的無障礙名稱 |
className | string | — | 透傳到最外層容器 |
RadioGroupOption
| 欄位 | 型別 | 預設值 | 說明 |
|---|---|---|---|
value | string | — | 選項值(同一群組內不可重複) |
label | ReactNode | — | 選項標籤 |
description | ReactNode | — | 補充說明,以 aria-describedby 關聯 |
disabled | boolean | false | 停用此選項:不可點擊、方向鍵會跳過 |
meta | ReactNode | — | card 變體右上角的附加資訊(例如價格);dot 變體不顯示 |
細節
- 選中外框只渲染在選中的那張卡片裡,靠
layoutId讓 motion 在卡片之間補間位置與尺寸;layoutId以useId為前綴,同頁多組互不干擾。 - 取消選中的內圓不用彈簧,150ms 直接收起,避免兩顆圓點同時晃動。
- 邊框與文字顏色過渡使用
--wb-radio-group-duration(預設150ms)與--wb-ease-out,可在全域或外層容器覆寫。 - 提供
name時只渲染一個 hidden input,值為目前選中項;未選取時送出空字串。
可及性
- 根元素為
role="radiogroup"並帶aria-orientation;每項是role="radio"的button,以aria-checked標示選中,標籤與說明分別以aria-labelledby、aria-describedby關聯 - roving tabindex:整組只有一個 Tab 停靠點(選中項,沒有選中時為第一個可用項)
- ↑/←、↓/→ 移動焦點並同時選取,跳過停用項、首尾循環;Space 選取目前聚焦項
- 鍵盤焦點顯示
focus-visible外框,與選中外框分開,不會混淆 - 使用者系統開啟「減少動態效果」時,內圓不再彈簧放大、外框不再滑動,改為 100ms 淡入直接切換