コンテンツへスキップ

リストボックス

チェック済みとチェック解除の状態を切り替えることができるコントロールです。
果物
リンゴ
バナナ
ブルーベリー
ブドウ
パイナップル
野菜
ナス
ブロッコリー
ニンジン
ズッキーニ
リーク
vue
<script setup lang="ts">
import { Icon } from '@iconify/vue'
import { ListboxContent, ListboxGroup, ListboxGroupLabel, ListboxItem, ListboxItemIndicator, ListboxRoot } from 'radix-vue'

const fruits = ['Apple', 'Banana', 'Blueberry', 'Grapes', 'Pineapple']
const vegetables = ['Aubergine', 'Broccoli', 'Carrot', 'Courgette', 'Leek']
</script>

<template>
  <ListboxRoot class=" flex flex-col rounded-lg border bg-white text-green9 mx-auto ">
    <ListboxContent class="p-[5px] w-48 h-72 overflow-auto">
      <ListboxGroup>
        <ListboxGroupLabel class="px-[25px] text-xs leading-[25px] text-mauve11">
          Fruits
        </ListboxGroupLabel>
        <ListboxItem
          v-for="i in fruits"
          :key="i"
          :value="i"
          class="w-full flex items-center px-[25px] h-[25px] leading-none text-[13px] relative text-green9 select-none outline-none data-[highlighted]:ring-green9 data-[highlighted]:ring-1 focus:ring-green9 focus:ring-1  data-[state=checked]:bg-green9 data-[state=checked]:text-white data-[disabled]:opacity-50 rounded"
        >
          <ListboxItemIndicator
            class="absolute left-0 w-[25px] inline-flex items-center justify-center"
          >
            <Icon icon="radix-icons:check" />
          </ListboxItemIndicator>
          <span>{{ i }}</span>
        </ListboxItem>
      </ListboxGroup>

      <ListboxGroup class="mt-2">
        <ListboxGroupLabel class="px-[25px] text-xs leading-[25px] text-mauve11">
          Vegetables
        </ListboxGroupLabel>
        <ListboxItem
          v-for="i in vegetables"
          :key="i"
          :value="i"
          class="w-full flex items-center px-[25px] h-[25px] leading-none text-[13px] relative text-green9 select-none outline-none data-[highlighted]:ring-green9 data-[highlighted]:ring-1 focus:ring-green9 focus:ring-1  data-[state=checked]:bg-green9 data-[state=checked]:text-white data-[disabled]:opacity-50 rounded"
        >
          <ListboxItemIndicator
            class="absolute left-0 w-[25px] inline-flex items-center justify-center"
          >
            <Icon icon="radix-icons:check" />
          </ListboxItemIndicator>
          <span>{{ i }}</span>
        </ListboxItem>
      </ListboxGroup>
    </ListboxContent>
  </ListboxRoot>
</template>

機能

  • 制御可能または非制御可能です。
  • アイテム、ラベル、アイテムのグループをサポートします。
  • フォーカスは完全に管理されています。
  • 完全なキーボードナビゲーション。
  • 右から左への方向をサポートします。
  • 異なる選択動作。

インストール

コマンドラインからコンポーネントをインストールします。

sh
$ npm add radix-vue

構成

すべての部品をインポートして組み立てます。

vue
<script setup>
import { ListboxContent, ListboxFilter, ListboxGroup, ListboxGroupLabel, ListboxItem, ListboxItemIndicator, ListboxRoot, ListboxVirtualizer } from 'radix-vue'
</script>

<template>
  <ListboxRoot>
    <ListboxFilter />

    <ListboxContent>
      <ListboxItem>
        <ListboxItemIndicator />
      </ListboxItem>

      <!-- or with group -->
      <ListboxGroup>
        <ListboxGroupLabel />
        <ListboxItem>
          <ListboxItemIndicator />
        </ListboxItem>
      </ListboxGroup>

      <!-- or with virtual -->
      <ListboxVirtualizer>
        <ListboxItem>
          <ListboxItemIndicator />
        </ListboxItem>
      </ListboxVirtualizer>
    </ListboxContent>
  </ListboxRoot>
</template>

APIリファレンス

ルート

リストボックスのすべての部品を含みます。フォーム内で使用すると、イベントが正しく伝播するように`input`もレンダリングされます。

プロパティデフォルト値
as
'div'
AsTag | コンポーネント

このコンポーネントがレンダリングされる要素またはコンポーネント。`asChild`で上書きできます。

asChild
boolean

子として渡された要素に対して、デフォルトでレンダリングされる要素を変更し、そのプロパティと動作をマージします。

詳細はコンポジションガイドをご覧ください。

by
string | ((a: AcceptableValue, b: AcceptableValue) => boolean)

特定のフィールドでオブジェクトを比較するためにこれを使用するか、オブジェクトの比較方法を完全に制御するために独自の比較関数を渡します。

defaultValue
AcceptableValue | AcceptableValue[]

最初にレンダリングされたときのリストボックスの値。リストボックスの状態を制御する必要がない場合に使用します。

dir
'ltr' | 'rtl'

該当する場合のリストボックスの読み取り方向。
省略した場合、グローバルに`ConfigProvider`から継承するか、LTR(左から右)の読み取りモードとします。

disabled
boolean

`true`の場合、ユーザーがリストボックスと対話することを防ぎます。

highlightOnHover
boolean

`true`の場合、アイテムにホバーするとハイライトがトリガーされます。

modelValue
AcceptableValue | AcceptableValue[]

リストボックスの制御された値。`v-model`でバインドできます。

multiple
boolean

複数のオプションを選択できるかどうか。

name
string

リストボックスの名前。名前/値のペアの一部として、所有するフォームと共に送信されます。

orientation
'vertical'
'vertical' | 'horizontal'

リストボックスの方向。
主に、矢印ナビゲーションがそれに応じて行われるためです(左右対上下)。

selectionBehavior
'toggle'
'replace' | 'toggle'

コレクションで複数の選択をどのように動作させるか。

イベントペイロード
entryFocus
[イベント: CustomEvent<any>]

コンテナにフォーカスされているときに呼び出されるイベントハンドラ。防止できます。

highlight
[ペイロード: { ref: HTMLElement; value: AcceptableValue; }]

ハイライトされた要素が変更されたときのイベントハンドラ。

leave
[イベント: Event]

マウスがコンテナから離れたときに呼び出されるイベントハンドラ。

update:modelValue
[value: AcceptableValue]

値が変更されたときに呼び出されるイベントハンドラ。

スロット (デフォルト)ペイロード
modelValue
AcceptableValue | AcceptableValue[] | undefined

現在の有効な値

データ属性
[data-disabled]無効な場合に存在します。

フィルター

フィルタリングを実行するための入力要素。

プロパティデフォルト値
as
'input'
AsTag | コンポーネント

このコンポーネントがレンダリングされる要素またはコンポーネント。`asChild`で上書きできます。

asChild
boolean

子として渡された要素に対して、デフォルトでレンダリングされる要素を変更し、そのプロパティと動作をマージします。

詳細はコンポジションガイドをご覧ください。

autoFocus
boolean

マウント時に要素にフォーカスします。

modelValue
string

フィルターの制御された値。`v-model`でバインドできます。

イベントペイロード
update:modelValue
[string]

値が変更されたときに呼び出されるイベントハンドラ。

スロット (デフォルト)ペイロード
modelValue
string | undefined

現在の入力値

データ属性
[data-disabled]無効な場合に存在します。

コンテンツ

すべてのリストボックスグループとアイテムを含みます。

プロパティデフォルト値
as
'div'
AsTag | コンポーネント

このコンポーネントがレンダリングされる要素またはコンポーネント。`asChild`で上書きできます。

asChild
boolean

子として渡された要素に対して、デフォルトでレンダリングされる要素を変更し、そのプロパティと動作をマージします。

詳細はコンポジションガイドをご覧ください。

アイテム

アイテムコンポーネント。

プロパティデフォルト値
as
'div'
AsTag | コンポーネント

このコンポーネントがレンダリングされる要素またはコンポーネント。`asChild`で上書きできます。

asChild
boolean

子として渡された要素に対して、デフォルトでレンダリングされる要素を変更し、そのプロパティと動作をマージします。

詳細はコンポジションガイドをご覧ください。

disabled
boolean

`true`の場合、ユーザーがアイテムと対話することを防ぎます。

value*
AcceptableValue

`name`と共に送信されたデータとして与えられた値。

イベントペイロード
select
[イベント: SelectEvent<AcceptableValue>]

アイテムを選択したときに呼び出されるイベントハンドラ。
`event.preventDefault`を呼び出すことで防止できます。

データ属性
[data-state]"checked" | "unchecked"
[data-highlighted]ハイライトされている場合に存在します。
[data-disabled]無効な場合に存在します。

アイテムインジケーター

アイテムが選択されている場合にレンダリングされます。この要素を直接スタイル設定するか、アイコンを配置するためのラッパーとして使用するか、その両方を使用できます。

プロパティデフォルト値
as
'span'
AsTag | コンポーネント

このコンポーネントがレンダリングされる要素またはコンポーネント。`asChild`で上書きできます。

asChild
boolean

子として渡された要素に対して、デフォルトでレンダリングされる要素を変更し、そのプロパティと動作をマージします。

詳細はコンポジションガイドをご覧ください。

グループ

複数のアイテムをグループ化するために使用します。自動ラベル付けによるアクセシビリティを確保するために、`ListboxGroupLabel`と組み合わせて使用します。

プロパティデフォルト値
as
'div'
AsTag | コンポーネント

このコンポーネントがレンダリングされる要素またはコンポーネント。`asChild`で上書きできます。

asChild
boolean

子として渡された要素に対して、デフォルトでレンダリングされる要素を変更し、そのプロパティと動作をマージします。

詳細はコンポジションガイドをご覧ください。

グループラベル

グループのラベルをレンダリングするために使用します。矢印キーを使用してフォーカスすることはできません。

プロパティデフォルト値
as
'div'
AsTag | コンポーネント

このコンポーネントがレンダリングされる要素またはコンポーネント。`asChild`で上書きできます。

asChild
boolean

子として渡された要素に対して、デフォルトでレンダリングされる要素を変更し、そのプロパティと動作をマージします。

詳細はコンポジションガイドをご覧ください。

for
string

仮想化

リストの仮想化を実現するための仮想コンテナ。

プロパティデフォルト値
estimateSize
number

各アイテムの推定サイズ(px単位)。

options*
AcceptableValue[]

アイテムのリスト

textContent
((option: AcceptableValue) => string)

タイプアヘッド機能を実現するための各アイテムのテキストコンテンツ。

スロット (デフォルト)ペイロード
option
string | number | false | true | Record<string, any>

値としてオブジェクトをバインドする

値として文字列のみを提供できるネイティブHTMLフォームコントロールとは異なり、`radix-vue`は複雑なオブジェクトのバインドもサポートします。

vue
<script setup lang="ts">
import { ref } from 'vue'
import { ListboxContent, ListboxFilter, ListboxItem, ListboxRoot } from 'radix-vue'

const people = [
  { id: 1, name: 'Durward Reynolds' },
  { id: 2, name: 'Kenton Towne' },
  { id: 3, name: 'Therese Wunsch' },
  { id: 4, name: 'Benedict Kessler' },
  { id: 5, name: 'Katelyn Rohan' },
]
const selectedPeople = ref(people[0])
</script>

<template>
  <ListboxRoot v-model="selectedPeople">
    <ListboxContent>
      <ListboxItem
        v-for="person in people"
        :key="person.id"
        :value="person"
        :disabled="person.unavailable"
      >
        {{ person.name }}
      </ListboxItem>
    </ListboxContent>
  </ListboxRoot>
</template>

複数の値を選択する

`Listbox`コンポーネントを使用すると、複数の値を選択できます。単一の値ではなく、値の配列を提供することで、これを有効にできます。

vue
<script setup lang="ts">
import { ref } from 'vue'
import { ListboxRoot } from 'radix-vue'

const people = [
  { id: 1, name: 'Durward Reynolds' },
  { id: 2, name: 'Kenton Towne' },
  { id: 3, name: 'Therese Wunsch' },
  { id: 4, name: 'Benedict Kessler' },
  { id: 5, name: 'Katelyn Rohan' },
]
const selectedPeople = ref([people[0], people[1]])
</script>

<template>
  <ListboxRoot
    v-model="selectedPeople"
    multiple
  >
    ...
  </ListboxRoot>
</template>

カスタムフィルタリング

vue
<script setup lang="ts">
import { ref } from 'vue'
import { ListboxContent, ListboxFilter, ListboxItem, ListboxRoot } from 'radix-vue'

const people = [
  { id: 1, name: 'Durward Reynolds' },
  { id: 2, name: 'Kenton Towne' },
  { id: 3, name: 'Therese Wunsch' },
  { id: 4, name: 'Benedict Kessler' },
  { id: 5, name: 'Katelyn Rohan' },
]
const selectedPeople = ref(people[0])
const searchTerm = ref('')

const filteredPeople = computed(() =>
  searchTerm.value === ''
    ? people
    : people.filter((person) => {
      return person.name.toLowerCase().includes(searchTerm.value.toLowerCase())
    })
)
</script>

<template>
  <ListboxRoot
    v-model="selectedPeople"
  >
    <ListboxFilter v-model="searchTerm" />
    <ListboxContent>
      <ListboxItem
        v-for="person in filteredPeople"
        :key="person.id"
        :value="person"
      >
        {{ person.name }}
      </ListboxItem>
    </ListboxContent>
  </ListboxRoot>
</template>

仮想リスト

長いアイテムリストのレンダリングはアプリを遅くする可能性があるため、仮想化を使用するとパフォーマンスが大幅に向上します。

vue
<script setup lang="ts">
import { ref } from 'vue'
import { ListboxContent, ListboxFilter, ListboxItem, ListboxRoot, ListboxVirtualizer } from 'radix-vue'

const people = [
  { id: 1, name: 'Durward Reynolds' },
  { id: 2, name: 'Kenton Towne' },
  { id: 3, name: 'Therese Wunsch' },
  { id: 4, name: 'Benedict Kessler' },
  { id: 5, name: 'Katelyn Rohan' },
  // and a lot more
]
</script>

<template>
  <ListboxRoot>
    <ListboxContent>
      <!-- checkout https://radix-vue.com/components/listbox.html#virtualizer -->
      <ListboxVirtualizer
        v-slot="{ option }"
        :options="people"
        :text-content="(opt) => opt.name"
      >
        <ListboxItem :value="option">
          {{ person.name }}
        </ListboxItem>
      </ListboxVirtualizer>
    </ListboxContent>
  </ListboxRoot>
</template>

アクセシビリティ

Listbox WAI-ARIAデザインパターンに準拠しています。

キーボード操作

キー説明
Enter
`ListboxItem`でハイライトされている場合、フォーカスされているアイテムを選択します。
下矢印
`ListboxItem`にフォーカスがある場合、フォーカスを次のアイテムに移動します。
上矢印
ListboxItemがフォーカスされている場合、前の項目にフォーカスを移動します。
ホーム
最初の項目にフォーカスとハイライトを移動します。
エンド
最後の項目にフォーカスとハイライトを移動します。
Ctrl/Cmd + A
すべての項目を選択します。