チェックボックス
チェックボックスは、ネイティブの HTML チェックボックスと同じ機能を提供しますが、スタイルは一切適用されません。そのため、自由にデザインできます。
インストール
はじめに、npm を使用して Headless UI をインストールします。
npm install @headlessui/react
基本的な例
チェックボックスは Checkbox
コンポーネントを使用して構築されます。コンポーネントを直接クリックするか、フォーカスされている間にスペースバーを押すことで、チェックボックスを切り替えることができます。
チェックボックスを切り替えると、新しい checked
値を使用して onChange
関数が呼び出されます。
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 は、チェックボックスがオンになっているかどうか、ポップオーバーが開いているか閉じているか、メニューのどの項目が現在キーボードでフォーカスされているかなど、各コンポーネントに関する多くの状態を追跡します。
ただし、コンポーネントはヘッドレスで、初期状態ではスタイルがまったく適用されていないため、各状態に必要なスタイルを自分で提供するまで、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 を参照してください。
例
ラベルの追加
Label
と Checkbox
を Field
コンポーネントでラップして、生成された 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
をクリックすると、ネイティブ HTML チェックボックスのラベルと同様に、Checkbox
が切り替わります。Label
をクリックできないようにするには、Label
コンポーネントに passive
プロパティを追加します。
<Label passive>Enable beta features</Label>
説明の追加
Field
内で Description
コンポーネントを使用して、aria-describedby
属性を使用して Checkbox
と自動的に関連付けます。
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> )
}
チェックボックスの無効化
Field
コンポーネントに disabled
プロパティを追加して、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>
)
}
Checkbox
自体に disabled プロパティを直接追加することで、Field
の外部でチェックボックスを無効にすることもできます。
HTML フォームでの使用
Checkbox
に name
プロパティを追加すると、非表示の 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 フォームでチェックボックスを使用する場合、または React の状態を使用して追跡する代わりに FormData を使用して状態を収集するフォーム API を使用する際に、コードを簡素化できます。
副作用を実行する必要がある場合に備えて、コンポーネントの値が変更されたときに、提供した 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 コンポーネントは、Framer Motion や React Spring などの React エコシステムの他のアニメーションライブラリとも適切に連携します。
異なる要素としてのレンダリング
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 | String | Component チェックボックスをレンダリングする要素またはコンポーネント。チェックボックスとしてレンダリングする必要があります。 |
checked | — | Boolean チェックボックスがオンになっているかどうか。 |
defaultChecked | — | T 非制御コンポーネントとして使用する場合のデフォルトのチェック値。 |
onChange | — | (value: Boolean) => void チェックボックスが切り替えられたときに呼び出される関数。 |
indeterminate | — | Boolean チェックボックスが不確定状態かどうか。 |
disabled | false | Boolean チェックボックスがチェックボックス無効になっているかどうか。. |
autoFocus | false | Boolean チェックボックスがチェックボックス最初にレンダリングされたときにフォーカスを受け取るかどうか。 |
name | — | String チェックボックスをチェックボックスフォーム内で使用する場合の名前。 |
form | — | String チェックボックスが属するフォームのID。チェックボックスに属します。
|
value | — | String このコンポーネントをフォーム内で使用する場合、チェックされている場合に使用される値。 |
データ属性 | レンダープロップ | 説明 |
data-checked | checked |
チェックボックスがチェックボックスチェックされています。 |
data-indeterminate | indeterminate |
チェックボックスがチェックボックス不確定状態です。 |
data-disabled | disabled |
チェックボックスがチェックボックス無効になっています。 |
data-focus | focus |
チェックボックスがチェックボックスフォーカスされています。 |
data-hover | hover |
チェックボックスがチェックボックスホバーされています。 |
data-active | active |
チェックボックスがチェックボックスアクティブまたは押下状態です。 |
data-autofocus | autofocus |
|
data-changing | changing |
チェック状態が現在変更中かどうか。
|
Label
、Description
、およびフォームコントロールをまとめてグループ化します。
プロパティ | デフォルト | 説明 |
as | div | String | Component チェックボックスをレンダリングする要素またはコンポーネント。fieldとしてレンダリングする必要があります。 |
disabled | false | Boolean フィールドが無効になっているかどうか。 |
データ属性 | レンダープロップ | 説明 |
data-disabled | disabled |
フィールドが無効になっているかどうか。 |
Label
コンポーネントは、フォームコントロールにラベルを付けます。
プロパティ | デフォルト | 説明 |
as | label | String | Component チェックボックスをレンダリングする要素またはコンポーネント。labelとしてレンダリングする必要があります。 |
passive | false | Boolean trueの場合、ラベルをクリックしても関連付けられたフォームコントロールにフォーカスが当たりません。 |
データ属性 | レンダープロップ | 説明 |
data-disabled | disabled |
親の |
Description
コンポーネントは、フォームコントロールについて説明します。
プロパティ | デフォルト | 説明 |
as | p | String | Component チェックボックスをレンダリングする要素またはコンポーネント。descriptionとしてレンダリングする必要があります。 |
データ属性 | レンダープロップ | 説明 |
data-disabled | disabled |
親の |
あらかじめデザインされたTailwind CSSチェックボックスコンポーネントの例に興味がある場合は、Tailwind UIをご覧ください。美しくデザインされ、巧みに作られたコンポーネントのコレクションです。
これは、このようなオープンソースプロジェクトへの私たちの取り組みをサポートするための素晴らしい方法であり、私たちがそれらを改善し、適切に維持することを可能にします。