輸入元件

描邊核取方塊

勾選時勾號描邊畫出、方塊微縮放回彈的 React 核取方塊元件,半選橫線與勾號之間平滑變形,群組全選時各項依序錯開勾上。

勾選時勾號沿著筆劃描邊畫出、方塊在狀態變化瞬間微縮再以彈簧回彈的核取方塊。半選(indeterminate)橫線與勾號是同一條路徑,兩者之間平滑變形而不是直接替換。搭配 DrawnCheckbox.Group 可以做出帶「全選」列的清單:全選列自動計算勾選/半選,一次勾滿或清空時各項依畫面順序錯開動畫。單一核取方塊與群組都支援受控/非受控雙模式。

把這個效果裝進你的專案

在專案資料夾執行指令,CLI 會加入原始碼與依賴套件,再依下方使用範例引用元件。

npx webberui@latest add drawn-checkbox

還沒有專案,或安裝遇到問題?看快速開始 →

Playground

即時調整 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型別預設值說明
checkedboolean | "indeterminate"—受控狀態;未提供時由元件內部管理(非受控)。傳 "indeterminate" 顯示半選
defaultCheckedboolean | "indeterminate"false非受控模式的初始狀態
onCheckedChange(next: boolean) => void—狀態變動時回呼;從半選點擊一律變為 true
indeterminatebooleanfalse便利 prop:為 true 時顯示半選,等同 checked="indeterminate"
size"sm" | "md" | "lg""md"方塊尺寸:sm 14px、md 16px、lg 20px
durationnumber180勾號描邊動畫時長(ms);取消勾選的收回時長為一半
labelReactNode—右側標籤文字,點擊標籤也會切換
descriptionReactNode—標籤下方的補充說明
disabledbooleanfalse停用
namestring—表單欄位名稱;有提供時以 hidden input 送出(僅勾選時)
valuestring—表單送出值;在 Group 內時作為該項的識別值
selectAllbooleanfalse在 Group 內作為「全選」列:自動計算勾選/半選,點擊時一次勾滿或清空
classNamestring—透傳到最外層容器

DrawnCheckbox.Group

欄位型別預設值說明
valuestring[]—受控的已勾選 value 清單;未提供時由元件內部管理(非受控)
defaultValuestring[][]非受控模式的初始勾選清單
onValueChange(value: string[]) => void—勾選清單變動時回呼
orientation"vertical" | "horizontal""vertical"排列方向
staggernumber30全選/清空時各項動畫依 DOM 順序錯開的間隔(ms)
aria-labelledbystring—指向群組標題元素的 id
aria-labelstring—沒有可見標題時的群組名稱
childrenReactNode—帶 value 的 DrawnCheckbox 子項,可另加一個帶 selectAll 的全選列
classNamestring—透傳到群組根元素

細節

  • 勾號是一條自繪 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 淡入直接出現