リストボックス
<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>
機能
- 制御可能または非制御可能です。
- アイテム、ラベル、アイテムのグループをサポートします。
- フォーカスは完全に管理されています。
- 完全なキーボードナビゲーション。
- 右から左への方向をサポートします。
- 異なる選択動作。
インストール
コマンドラインからコンポーネントをインストールします。
$ npm add radix-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' 該当する場合のリストボックスの読み取り方向。 | |
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>] アイテムを選択したときに呼び出されるイベントハンドラ。 |
データ属性 | 値 |
---|---|
[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`は複雑なオブジェクトのバインドもサポートします。
<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`コンポーネントを使用すると、複数の値を選択できます。単一の値ではなく、値の配列を提供することで、これを有効にできます。
<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>
カスタムフィルタリング
<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>
仮想リスト
長いアイテムリストのレンダリングはアプリを遅くする可能性があるため、仮想化を使用するとパフォーマンスが大幅に向上します。
<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 | すべての項目を選択します。 |