チェックボックス
チェックボックスは、ネイティブの 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 | Booleantrueの場合、ラベルをクリックしても関連付けられたフォームコントロールにフォーカスが当たりません。 | 
| データ属性 | レンダープロップ | 説明 | 
| data-disabled | disabled | 
 親の  | 
Description コンポーネントは、フォームコントロールについて説明します。
| プロパティ | デフォルト | 説明 | 
| as | p | String | Componentチェックボックスをレンダリングする要素またはコンポーネント。descriptionとしてレンダリングする必要があります。 | 
| データ属性 | レンダープロップ | 説明 | 
| data-disabled | disabled | 
 親の  | 
あらかじめデザインされたTailwind CSSチェックボックスコンポーネントの例に興味がある場合は、Tailwind UIをご覧ください。美しくデザインされ、巧みに作られたコンポーネントのコレクションです。
これは、このようなオープンソースプロジェクトへの私たちの取り組みをサポートするための素晴らしい方法であり、私たちがそれらを改善し、適切に維持することを可能にします。
