核取方塊
核取方塊提供與本機 HTML 核取方塊相同的功能,但沒有任何樣式設定,讓你可以自由設計任何你想要的樣式。
To get started, install Headless UI via npm
npm install @headlessui/react
核取方塊是用 Checkbox
元件建構的。您可以點選元件或是在聚焦時按空白鍵來切換核取方塊。
切換核取方塊會呼叫 onChange
函式,帶有新的 checked
值。
import { Checkbox } from '@headlessui/react'
import { useState } from 'react'
function Example() {
const [enabled, setEnabled] = useState(false)
return (
<Checkbox
checked={enabled}
onChange={setEnabled}
className="group block size-4 rounded border bg-white data-[checked]:bg-blue-500"
>
{/* Checkmark icon */}
<svg className="stroke-white opacity-0 group-data-[checked]:opacity-100" viewBox="0 0 14 14" fill="none">
<path d="M3 8L6 11L11 3.5" strokeWidth={2} strokeLinecap="round" strokeLinejoin="round" />
</svg>
</Checkbox>
)
}
Headless UI 會追蹤每個元件的許多狀態,例如核取方塊是否已勾選、快顯視窗是否開啟或關閉,或功能表中目前由鍵盤聚焦的項目為何。
但是,由於元件預設是 headless 且完全沒有樣式,您無法在 UI 中看到這些資訊,直到您自行提供希望套用於各個狀態的樣式。
調整 Headless UI 元件不同狀態最簡單的方法是使用每個元件公開的 data-*
屬性。
例如,Checkbox
元件公開一個 data-checked
屬性,它會指出核取方塊目前是否已勾選,以及一個 data-disabled
屬性,它會指出核取方塊目前是否已停用。
<!-- Rendered `Checkbox` -->
<span role="checkbox" data-checked data-disabled>
<!-- ... -->
</span>
使用 CSS 屬性選擇器 來有條件地套用樣式,根據這些資料屬性的存在與否。如果您使用 Tailwind CSS,資料屬性修改器 會讓這件事變得很容易
import { Checkbox } from '@headlessui/react'
import { useState } from 'react'
function Example() {
const [enabled, setEnabled] = useState(false)
return (
<Checkbox
checked={enabled}
onChange={setEnabled}
className="group block size-4 rounded border bg-white data-[checked]:bg-blue-500 data-[disabled]:cursor-not-allowed data-[disabled]:opacity-50 data-[checked]:data-[disabled]:bg-gray-500" >
<svg className="stroke-white opacity-0 group-data-[checked]:opacity-100" viewBox="0 0 14 14" fill="none"> <path d="M3 8L6 11L11 3.5" strokeWidth={2} strokeLinecap="round" strokeLinejoin="round" />
</svg>
</Checkbox>
)
}
請參閱 元件 API 查看所有可用的資料屬性清單。
每個元件也會透過 渲染道具 公開其目前狀態的資訊,您可以使用它來有條件地套用不同的樣式或渲染不同的內容。
例如,Checkbox
元件公開一個 checked
狀態,它會指出核取方塊目前是否已勾選,以及一個 disabled
狀態,它會指出核取方塊目前是否已停用。
import { Checkbox } from '@headlessui/react'
import clsx from 'clsx'
import { Fragment, useState } from 'react'
function Example() {
const [enabled, setEnabled] = useState(false)
return (
<Checkbox checked={enabled} onChange={setEnabled} as={Fragment}>
{({ checked, disabled }) => ( <span
className={clsx(
'block size-4 rounded border',
!checked && 'bg-white', checked && !disabled && 'bg-blue-500', checked && disabled && 'bg-gray-500', disabled && 'cursor-not-allowed opacity-50' )}
>
<svg className={clsx('stroke-white', checked ? 'opacity-100' : 'opacity-0')} viewBox="0 0 14 14" fill="none"> <path d="M3 8L6 11L11 3.5" strokeWidth={2} strokeLinecap="round" strokeLinejoin="round" />
</svg>
</span>
)} </Checkbox>
)
}
請參閱 元件 API 查看所有可用的渲染道具清單。
用 Field
元件包裝 Label
和 Checkbox
,以自動關聯它們並使用產生的 ID
import { useState } from 'react'
import { Checkbox, Field, Label } from '@headlessui/react'
function Example() {
const [enabled, setEnabled] = useState(false)
return (
<Field className="flex items-center gap-2"> <Checkbox
checked={enabled}
onChange={setEnabled}
className="group block size-4 rounded border bg-white data-[checked]:bg-blue-500"
>
<svg className="stroke-white opacity-0 group-data-[checked]:opacity-100" viewBox="0 0 14 14" fill="none">
<path d="M3 8L6 11L11 3.5" strokeWidth={2} strokeLinecap="round" strokeLinejoin="round" />
</svg>
</Checkbox>
<Label>Enable beta features</Label> </Field> )
}
預設上,按一下 Label
將切換 Checkbox
,就像標籤對原生 HTML 核取方塊的動作。如果你想讓 Label
不可按,你可以新增一個 passive
道具到 Label
元件
<Label passive>Enable beta features</Label>
在一個 Field
內使用 Description
元件,以自動關聯它與 Checkbox
,使用 aria-describedby
屬性
import { Checkbox, Description, Field, Label } from '@headlessui/react'
import { useState } from 'react'
function Example() {
const [enabled, setEnabled] = useState(false)
return (
<Field> <Label>Enable beta features</Label>
<Description>This will give you early access to new features we're developing.</Description> <Checkbox
checked={enabled}
onChange={setEnabled}
className="group block size-4 rounded border bg-white data-[checked]:bg-blue-500"
>
<svg className="stroke-white opacity-0 group-data-[checked]:opacity-100" viewBox="0 0 14 14" fill="none">
<path d="M3 8L6 11L11 3.5" strokeWidth={2} strokeLinecap="round" strokeLinejoin="round" />
</svg>
</Checkbox>
</Field> )
}
新增 disabled
道具到 Field
元件來停用一個 Checkbox
與它關聯的 Label
和 Description
import { Checkbox, Description, Field, Label } from '@headlessui/react'
import { useState } from 'react'
function Example() {
const [enabled, setEnabled] = useState(false)
return (
<Field disabled> <Label className="data-[disabled]:opacity-50">Enable beta features</Label>
<Description className="data-[disabled]:opacity-50">
This will give you early access to new features we're developing.
</Description>
<Checkbox
checked={enabled}
onChange={setEnabled}
className="group block size-4 rounded border bg-white data-[checked]:bg-blue-500 data-[disabled]:cursor-not-allowed data-[disabled]:opacity-50 data-[checked]:data-[disabled]:bg-gray-500"
>
<svg className="stroke-white opacity-0 group-data-[checked]:opacity-100" viewBox="0 0 14 14" fill="none">
<path d="M3 8L6 11L11 3.5" strokeWidth={2} strokeLinecap="round" strokeLinejoin="round" />
</svg>
</Checkbox>
</Field>
)
}
你也可以在 Field
外面停用一個核取方塊,直接把 disabled 道具新增到 Checkbox
本身即可。
如果你新增 name
道具到你的 Checkbox
,一個隱藏的 input
將會渲染,並與核取方塊狀態保持同步。
import { Checkbox } from '@headlessui/react'
import { useState } from 'react'
function Example() {
const [enabled, setEnabled] = useState(false)
return (
<form action="/accounts" method="post">
<Checkbox
checked={enabled}
onChange={setEnabled}
name="terms-of-service" className="group block size-4 rounded border bg-white data-[checked]:bg-blue-500"
>
<svg className="stroke-white opacity-0 group-data-[checked]:opacity-100" viewBox="0 0 14 14" fill="none">
<path d="M3 8L6 11L11 3.5" strokeWidth={2} strokeLinecap="round" strokeLinejoin="round" />
</svg>
</Checkbox>
<button>Submit</button>
</form>
)
}
這樣你可以用一個核取方塊在一個原生的 HTML <form>
內部,並像你的核取方塊是一個原生的 HTML 表單控制項一樣,做出傳統的表單提交。
預設上,值會是 on
當核取方塊被選中,當核取方塊沒選中時值不存在。
<!-- Rendered hidden input -->
<input type="hidden" name="terms-of-service" value="on" />
你可以在需要時使用 value
道具自訂值
import { Checkbox } from '@headlessui/react'
import { useState } from 'react'
function Example() {
const [enabled, setEnabled] = useState(false)
return (
<form action="/accounts" method="post">
<Checkbox
checked={enabled}
onChange={setEnabled}
name="terms-of-service"
value="accept" className="group block size-4 rounded border bg-white data-[checked]:bg-blue-500"
>
<svg className="stroke-white opacity-0 group-data-[checked]:opacity-100" viewBox="0 0 14 14" fill="none">
<path d="M3 8L6 11L11 3.5" strokeWidth={2} strokeLinecap="round" strokeLinejoin="round" />
</svg>
</Checkbox>
<button>Submit</button>
</form>
)
}
當核取方塊被選中時,隱藏的輸入項將使用你的自訂值
<!-- Rendered hidden input -->
<input type="hidden" name="terms-of-service" value="accept" />
像是字串的基本值將會渲染為一個包含這個值的單一隱藏輸入項,但是複雜的值像是物件會被編碼成多個輸入項,使用方括號表示法給它們命名。
如果你略過 checked
道具,Headless UI 將會在內部追蹤它的狀態,讓你用它當做 不受控的元件。
當不受控時,你可以使用 defaultChecked
道具預設勾選 Checkbox
。
import { Checkbox } from '@headlessui/react'
function Example() {
return (
<form action="/accounts" method="post">
<Checkbox
defaultChecked={true} name="terms-of-service"
className="group block size-4 rounded border bg-white data-[checked]:bg-blue-500"
>
<svg className="stroke-white opacity-0 group-data-[checked]:opacity-100" viewBox="0 0 14 14" fill="none">
<path d="M3 8L6 11L11 3.5" strokeWidth={2} strokeLinecap="round" strokeLinejoin="round" />
</svg>
</Checkbox>
<button>Submit</button>
</form>
)
}
這可以簡化你的程式碼,當使用核取方塊 與 HTML 表單一起 或是有 API 的表單用 FormData 而非用 React 的狀態追蹤它的狀態時。
您提供的任何 onChange
屬性仍可在元件值變更時呼叫,以防您需要執行任何副作用,但您不需要使用它來自行追蹤元件狀態。
由於核取方塊通常總是呈現在 DOM(而非像其他元件一樣會掛載/卸載),因此使用簡單的 CSS 轉場通常就足以為您的核取方塊增添動畫效果
import { Checkbox } from '@headlessui/react'
import { useState } from 'react'
function Example() {
const [enabled, setEnabled] = useState(false)
return (
<Checkbox
checked={enabled}
onChange={setEnabled}
className="group block size-4 rounded border bg-white transition data-[checked]:bg-blue-500" >
<svg
className="stroke-white opacity-0 transition group-data-[checked]:opacity-100" viewBox="0 0 14 14"
fill="none"
>
<path d="M3 8L6 11L11 3.5" strokeWidth={2} strokeLinecap="round" strokeLinejoin="round" />
</svg>
</Checkbox>
)
}
由於 Headless UI 元件沒有渲染,所以也可以與 React 生態系中其他動畫函式庫,例如 Framer Motion 和 React Spring 搭配使用。
Checkbox
元件預設會渲染 span
。請使用 as
屬性,讓元件以不同的元素或您自己的自訂元件渲染。
import { Checkbox } from '@headlessui/react'
import { useState } from 'react'
function Example() {
const [enabled, setEnabled] = useState(false)
return (
<Checkbox
as="div" checked={enabled}
onChange={setEnabled}
className="group block size-4 rounded border bg-white data-[checked]:bg-blue-500"
>
<svg className="stroke-white opacity-0 group-data-[checked]:opacity-100" viewBox="0 0 14 14" fill="none">
<path d="M3 8L6 11L11 3.5" strokeWidth={2} strokeLinecap="round" strokeLinejoin="round" />
</svg>
</Checkbox>
)
}
指令 | 說明 |
Space當 | 切換核取方塊 |
Enter當 | 提交父表單(如果存在) |
屬性 | 預設值 | 說明 |
as | span | 字串 | 元件 核取方塊應該要渲染為的元素或元件。 |
checked | — | 布林 表示核取方塊是否已勾選。 |
defaultChecked | — | T 使用非受控元件時的預設勾選值。 |
onChange | — | (value: Boolean) => void 當切換核取方塊時調用的函數。 |
indeterminate | — | 布林 表示核取方塊是否為不確定狀態。 |
disabled | false | 布林 表示應該要渲染為是否已停用. |
autoFocus | false | 布林 表示應該要渲染為初次渲染時是否會獲得焦點。 |
name | — | 字串 在應該要渲染為內使用時使用的名稱 |
表單。 | — | 字串 form應該要渲染為所屬 如若提供 |
值 | — | 字串 如於此組件內使用表單時使用的值,如已勾選。 |
資料屬性 | 呈現 Prop | 說明 |
data-checked | checked |
表示應該要渲染為已被勾選。 |
data-indeterminate | indeterminate |
表示應該要渲染為是未確定的。 |
data-disabled | disabled |
表示應該要渲染為已停用。 |
data-focus | focus |
表示應該要渲染為已被聚焦。 |
data-hover | hover |
表示應該要渲染為已被懸停。 |
data-active | active |
表示應該要渲染為是處於主動或被按下的狀態。 |
data-autofocus | autofocus |
|
data-changing | changing |
勾選狀態是否正在改變中。 當 |
將 標籤
、說明
及表單控制元件群組在一起。
屬性 | 預設值 | 說明 |
as | div | 字串 | 元件 核取方塊field的元素或元件。 |
disabled | false | 布林 欄位是否已停用。 |
資料屬性 | 呈現 Prop | 說明 |
data-disabled | disabled |
欄位是否已停用。 |
標籤
組件標記表單控制元件。
屬性 | 預設值 | 說明 |
as | label | 字串 | 元件 核取方塊label的元素或元件。 |
passive | false | 布林 當此為 true 時,按一下標籤不會對應表單控制元件焦點。 |
資料屬性 | 呈現 Prop | 說明 |
data-disabled | disabled |
父層 |
說明
組件說明表單控制元件。
屬性 | 預設值 | 說明 |
as | p | 字串 | 元件 核取方塊description的元素或元件。 |
資料屬性 | 呈現 Prop | 說明 |
data-disabled | disabled |
父層 |
如您有興趣了解預先設計的 Tailwind CSS 核取方塊組件範例,請查看 Tailwind UI — 由我們建置的一系列設計精美且製作精良的組件。
此為支持我們在類似此等開源專案工作的好方法,並能讓我們提升此等專案並保持良好維護。