チェックボックス

チェックボックスは、ネイティブの 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 を参照してください。

ラベルの追加

LabelCheckboxField コンポーネントでラップして、生成された 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 フォームでの使用

Checkboxname プロパティを追加すると、非表示の 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 MotionReact 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> ) }

コマンド説明

SpaceCheckbox にフォーカスがある場合

チェックボックスのオン/オフを切り替えます。

EnterCheckbox にフォーカスがある場合

親フォームが存在する場合は、それを送信します。

プロパティデフォルト説明
asspan
String | Component

チェックボックスをレンダリングする要素またはコンポーネント。チェックボックスとしてレンダリングする必要があります。

checked
Boolean

チェックボックスがオンになっているかどうか。

defaultChecked
T

非制御コンポーネントとして使用する場合のデフォルトのチェック値。

onChange
(value: Boolean) => void

チェックボックスが切り替えられたときに呼び出される関数。

indeterminate
Boolean

チェックボックスが不確定状態かどうか。

disabledfalse
Boolean

チェックボックスがチェックボックス無効になっているかどうか。.

autoFocusfalse
Boolean

チェックボックスがチェックボックス最初にレンダリングされたときにフォーカスを受け取るかどうか。

name
String

チェックボックスをチェックボックスフォーム内で使用する場合の名前。

form
String

チェックボックスが属するフォームのID。チェックボックスに属します。

name が指定されていて form が指定されていない場合、チェックボックスはチェックボックスその状態を最も近い祖先の form 要素に追加します。

value
String

このコンポーネントをフォーム内で使用する場合、チェックされている場合に使用される値。

データ属性レンダープロップ説明
data-checkedchecked

Boolean

チェックボックスがチェックボックスチェックされています。

data-indeterminateindeterminate

Boolean

チェックボックスがチェックボックス不確定状態です。

data-disableddisabled

Boolean

チェックボックスがチェックボックス無効になっています。

data-focusfocus

Boolean

チェックボックスがチェックボックスフォーカスされています。

data-hoverhover

Boolean

チェックボックスがチェックボックスホバーされています。

data-activeactive

Boolean

チェックボックスがチェックボックスアクティブまたは押下状態です。

data-autofocusautofocus

Boolean

autoFocus プロパティが true に設定されているかどうか。

data-changingchanging

Boolean

チェック状態が現在変更中かどうか。

checked 状態が変更されると、changing は 2 つのアニメーションフレームの間 true になり、トランジションを微調整できます。

LabelDescription、およびフォームコントロールをまとめてグループ化します。

プロパティデフォルト説明
asdiv
String | Component

チェックボックスをレンダリングする要素またはコンポーネント。fieldとしてレンダリングする必要があります。

disabledfalse
Boolean

フィールドが無効になっているかどうか。

データ属性レンダープロップ説明
data-disableddisabled

Boolean

フィールドが無効になっているかどうか。

Label コンポーネントは、フォームコントロールにラベルを付けます。

プロパティデフォルト説明
aslabel
String | Component

チェックボックスをレンダリングする要素またはコンポーネント。labelとしてレンダリングする必要があります。

passivefalse
Boolean

trueの場合、ラベルをクリックしても関連付けられたフォームコントロールにフォーカスが当たりません。

データ属性レンダープロップ説明
data-disableddisabled

Boolean

親の Field が無効になっているかどうか。

Description コンポーネントは、フォームコントロールについて説明します。

プロパティデフォルト説明
asp
String | Component

チェックボックスをレンダリングする要素またはコンポーネント。descriptionとしてレンダリングする必要があります。

データ属性レンダープロップ説明
data-disableddisabled

Boolean

親の Field が無効になっているかどうか。

あらかじめデザインされたTailwind CSSチェックボックスコンポーネントの例に興味がある場合は、Tailwind UIをご覧ください。美しくデザインされ、巧みに作られたコンポーネントのコレクションです。

これは、このようなオープンソースプロジェクトへの私たちの取り組みをサポートするための素晴らしい方法であり、私たちがそれらを改善し、適切に維持することを可能にします。