輸入元件
描邊核取方塊
勾選時勾號描邊畫出、方塊微縮放回彈的 React 核取方塊元件,半選橫線與勾號之間平滑變形,群組全選時各項依序錯開勾上。
勾選時勾號沿著筆劃描邊畫出、方塊在狀態變化瞬間微縮再以彈簧回彈的核取方塊。半選(indeterminate)橫線與勾號是同一條路徑,兩者之間平滑變形而不是直接替換。搭配 DrawnCheckbox.Group 可以做出帶「全選」列的清單:全選列自動計算勾選/半選,一次勾滿或清空時各項依畫面順序錯開動畫。單一核取方塊與群組都支援受控/非受控雙模式。
把這個效果裝進你的專案
在專案資料夾執行指令,CLI 會加入原始碼與依賴套件,再依下方使用範例引用元件。
npx webberui@latest add drawn-checkboxPlayground
即時調整 props、程式碼片段同步更新——直接試出你要的樣子再複製。
180
編輯中的呼叫預設屬性
<DrawnCheckbox/>
完整範例包含預覽的排版與資料。先安裝元件,再把範例檔貼入你的專案。
安裝
npx webberui@latest add https://webberui.com/r/drawn-checkbox.json或在 components.json 設定 registries 後,改用 @webberui/drawn-checkbox 安裝。
使用
import { DrawnCheckbox } from "@/components/ui/drawn-checkbox";
// 單一核取方塊(非受控)
<DrawnCheckbox label="接受服務條款" description="勾選後才能繼續下一步" />
// 群組 + 全選列
const [done, setDone] = React.useState<string[]>(["reply"]);
<DrawnCheckbox.Group value={done} onValueChange={setDone} aria-label="今日待辦">
<DrawnCheckbox selectAll label="全選" />
<DrawnCheckbox value="reply" label="回覆客戶信件" />
<DrawnCheckbox value="report" label="整理第三季報表" />
<DrawnCheckbox value="dentist" label="預約牙醫" description="已轉交給同事" disabled />
</DrawnCheckbox.Group>Props
| Prop | 型別 | 預設值 | 說明 |
|---|---|---|---|
checked | boolean | "indeterminate" | — | 受控狀態;未提供時由元件內部管理(非受控)。傳 "indeterminate" 顯示半選 |
defaultChecked | boolean | "indeterminate" | false | 非受控模式的初始狀態 |
onCheckedChange | (next: boolean) => void | — | 狀態變動時回呼;從半選點擊一律變為 true |
indeterminate | boolean | false | 便利 prop:為 true 時顯示半選,等同 checked="indeterminate" |
size | "sm" | "md" | "lg" | "md" | 方塊尺寸:sm 14px、md 16px、lg 20px |
duration | number | 180 | 勾號描邊動畫時長(ms);取消勾選的收回時長為一半 |
label | ReactNode | — | 右側標籤文字,點擊標籤也會切換 |
description | ReactNode | — | 標籤下方的補充說明 |
disabled | boolean | false | 停用 |
name | string | — | 表單欄位名稱;有提供時以 hidden input 送出(僅勾選時) |
value | string | — | 表單送出值;在 Group 內時作為該項的識別值 |
selectAll | boolean | false | 在 Group 內作為「全選」列:自動計算勾選/半選,點擊時一次勾滿或清空 |
className | string | — | 透傳到最外層容器 |
DrawnCheckbox.Group
| 欄位 | 型別 | 預設值 | 說明 |
|---|---|---|---|
value | string[] | — | 受控的已勾選 value 清單;未提供時由元件內部管理(非受控) |
defaultValue | string[] | [] | 非受控模式的初始勾選清單 |
onValueChange | (value: string[]) => void | — | 勾選清單變動時回呼 |
orientation | "vertical" | "horizontal" | "vertical" | 排列方向 |
stagger | number | 30 | 全選/清空時各項動畫依 DOM 順序錯開的間隔(ms) |
aria-labelledby | string | — | 指向群組標題元素的 id |
aria-label | string | — | 沒有可見標題時的群組名稱 |
children | ReactNode | — | 帶 value 的 DrawnCheckbox 子項,可另加一個帶 selectAll 的全選列 |
className | string | — | 透傳到群組根元素 |
細節
- 勾號是一條自繪 SVG 路徑,用
pathLength從 0 描到 1(時長 =duration、easeOut);取消勾選時以一半時長收回。 - 勾號與半選橫線都是「三個點」的路徑,
d屬性逐數字插值,所以勾 ↔ 橫線是平滑變形;從未勾選直接進入半選時,路徑先就位再描邊。 - 方塊在每次狀態變化時先縮到 0.9,再以 spring(stiffness 500、damping 25)彈回。
- 群組內的「全選」列只計算未停用的項目:全部勾選顯示勾、部分勾選顯示半選;點擊時只改動未停用項,停用項維持原狀。全選或清空時,真正改變狀態的項目依 DOM 順序延遲
i × stagger毫秒;單項切換不延遲。 - 色彩過渡時長讀取
--wb-drawn-checkbox-duration(預設 180ms);有傳duration時會同步覆寫這個變數,讓顏色與描邊同時完成。 - 在 Group 內時,子項的勾選狀態由 Group 的
value控制,checked/defaultChecked會被忽略。
可及性
- 方塊是
button,帶role="checkbox"與aria-checked(true/false/mixed);標籤以aria-labelledby、說明以aria-describedby關聯 - 點擊標籤也會切換;鍵盤以 Space 切換,Enter 不切換,與原生 checkbox 一致
- 鍵盤焦點顯示
focus-visible外框;停用時設定disabled,無法聚焦與切換 - 群組根元素為
role="group",可用aria-labelledby或aria-label命名 - 使用者系統開啟「減少動態效果」時,不描邊、不縮放、不錯開,勾號以 100ms 淡入直接出現