コンボボックス
<script setup lang="ts">
import { ref } from 'vue'
import { ComboboxAnchor, ComboboxContent, ComboboxEmpty, ComboboxGroup, ComboboxInput, ComboboxItem, ComboboxItemIndicator, ComboboxLabel, ComboboxRoot, ComboboxSeparator, ComboboxTrigger, ComboboxViewport } from 'radix-vue'
import { Icon } from '@iconify/vue'
const v = ref('')
const options = ['Apple', 'Banana', 'Blueberry', 'Grapes', 'Pineapple']
const vegetables = ['Aubergine', 'Broccoli', 'Carrot', 'Courgette', 'Leek']
</script>
<template>
<ComboboxRoot
v-model="v"
class="relative"
>
<ComboboxAnchor class="min-w-[160px] inline-flex items-center justify-between rounded px-[15px] text-[13px] leading-none h-[35px] gap-[5px] bg-white text-grass11 shadow-[0_2px_10px] shadow-black/10 hover:bg-mauve3 focus:shadow-[0_0_0_2px] focus:shadow-black data-[placeholder]:text-grass9 outline-none">
<ComboboxInput
class="!bg-transparent outline-none text-grass11 h-full selection:bg-grass5 placeholder-mauve8"
placeholder="Placeholder..."
/>
<ComboboxTrigger>
<Icon
icon="radix-icons:chevron-down"
class="h-4 w-4 text-grass11"
/>
</ComboboxTrigger>
</ComboboxAnchor>
<ComboboxContent class="absolute z-10 w-full mt-2 min-w-[160px] bg-white overflow-hidden rounded shadow-[0px_10px_38px_-10px_rgba(22,_23,_24,_0.35),_0px_10px_20px_-15px_rgba(22,_23,_24,_0.2)] will-change-[opacity,transform] data-[side=top]:animate-slideDownAndFade data-[side=right]:animate-slideLeftAndFade data-[side=bottom]:animate-slideUpAndFade data-[side=left]:animate-slideRightAndFade">
<ComboboxViewport class="p-[5px]">
<ComboboxEmpty class="text-mauve8 text-xs font-medium text-center py-2" />
<ComboboxGroup>
<ComboboxLabel class="px-[25px] text-xs leading-[25px] text-mauve11">
Fruits
</ComboboxLabel>
<ComboboxItem
v-for="(option, index) in options"
:key="index"
class="text-[13px] leading-none text-grass11 rounded-[3px] flex items-center h-[25px] pr-[35px] pl-[25px] relative select-none data-[disabled]:text-mauve8 data-[disabled]:pointer-events-none data-[highlighted]:outline-none data-[highlighted]:bg-grass9 data-[highlighted]:text-grass1"
:value="option"
>
<ComboboxItemIndicator
class="absolute left-0 w-[25px] inline-flex items-center justify-center"
>
<Icon icon="radix-icons:check" />
</ComboboxItemIndicator>
<span>
{{ option }}
</span>
</ComboboxItem>
<ComboboxSeparator class="h-[1px] bg-grass6 m-[5px]" />
</ComboboxGroup>
<ComboboxGroup>
<ComboboxLabel
class="px-[25px] text-xs leading-[25px] text-mauve11"
>
Vegetables
</ComboboxLabel>
<ComboboxItem
v-for="(option, index) in vegetables"
:key="index"
class="text-[13px] leading-none text-grass11 rounded-[3px] flex items-center h-[25px] pr-[35px] pl-[25px] relative select-none data-[disabled]:text-mauve8 data-[disabled]:pointer-events-none data-[highlighted]:outline-none data-[highlighted]:bg-grass9 data-[highlighted]:text-grass1"
:value="option"
>
<ComboboxItemIndicator
class="absolute left-0 w-[25px] inline-flex items-center justify-center"
>
<Icon icon="radix-icons:check" />
</ComboboxItemIndicator>
<span>
{{ option }}
</span>
</ComboboxItem>
</ComboboxGroup>
</ComboboxViewport>
</ComboboxContent>
</ComboboxRoot>
</template>
機能
- 制御または非制御にすることができます。
- 2つの配置モードを提供します。
- 項目、ラベル、項目のグループをサポートします。
- フォーカスは完全に管理されます。
- 完全なキーボードナビゲーション。
- カスタムプレースホルダーをサポートします。
- 右から左への方向をサポートします。
インストール
コマンドラインからコンポーネントをインストールします。
$ npm add radix-vue
構成
すべての部品をインポートして組み合わせてください。
<script setup lang="ts">
import {
ComboboxAnchor,
ComboboxArrow,
ComboboxCancel,
ComboboxContent,
ComboboxEmpty,
ComboboxGroup,
ComboboxInput,
ComboboxItem,
ComboboxItemIndicator,
ComboboxLabel,
ComboboxPortal,
ComboboxRoot,
ComboboxSeparator,
ComboboxTrigger,
ComboboxViewport,
} from 'radix-vue'
</script>
<template>
<ComboboxRoot>
<ComboboxAnchor>
<ComboboxInput />
<ComboboxTrigger />
<ComboboxCancel />
</ComboboxAnchor>
<ComboboxPortal>
<ComboboxContent>
<ComboboxViewport>
<ComboboxEmpty />
<ComboboxItem>
<ComboboxItemIndicator />
</ComboboxItem>
<ComboboxGroup>
<ComboboxLabel />
<ComboboxItem>
<ComboboxItemIndicator />
</ComboboxItem>
</ComboboxGroup>
<ComboboxSeparator />
</ComboboxViewport>
<ComboboxArrow />
</ComboboxContent>
</ComboboxPortal>
</ComboboxRoot>
</template>
APIリファレンス
ルート
コンボボックスのすべての部品を含みます
プロパティ | デフォルト | 型 |
---|---|---|
as | 'div' | AsTag | コンポーネント このコンポーネントがレンダリングされる要素またはコンポーネント。`asChild` で上書きできます。 |
asChild | boolean 子として渡された要素にデフォルトのレンダリング要素を変更し、それらのプロパティと動作をマージします。 詳細については、コンポジションガイドをご覧ください。 | |
defaultOpen | boolean 最初にレンダリングされたときのコンボボックスの開状態。 | |
defaultValue | AcceptableValue | AcceptableValue[] 最初にレンダリングされたときのコンボボックスの値。コンボボックスの状態を制御する必要がない場合に使用します。 | |
dir | 'ltr' | 'rtl' 該当する場合のコンボボックスの読み取り方向。 | |
disabled | boolean `true`の場合、ユーザーがコンボボックスと対話できなくなります。 | |
displayValue | ((val: AcceptableValue) => string) 選択された項目の入力の表示値。`multiple`では機能しません。 | |
filterFunction | ((val: string[] | number[] | false[] | true[] | Record<string, any>[], term: string) => string[] | number[] | false[] | true[] | Record<string, any>[]) `ComboboxItem`をフィルタリングするためのカスタムフィルタ関数。 | |
modelValue | AcceptableValue | AcceptableValue[] コンボボックスの制御された値。`v-model`でバインドできます。 | |
multiple | boolean 複数のオプションを選択できるかどうか。 | |
name | string コンボボックスの名前。名前/値のペアの一部として、所有するフォームと共に送信されます。 | |
open | boolean コンボボックスの制御された開状態。`v-model:open`でバインドできます。 | |
resetSearchTermOnBlur | true | boolean コンボボックスの入力がぼやけたときにsearchTermをリセットするかどうか。 |
searchTerm | string コンボボックスの制御された検索用語。`v-model:searchTerm`でバインドできます。 | |
selectedValue | AcceptableValue コンボボックスの現在強調表示されている値。`v-model:selectedValue`でバインドできます。 |
Emit | ペイロード |
---|---|
update:modelValue | [value: AcceptableValue] 値が変更されたときに呼び出されるイベントハンドラ。 |
update:open | [value: boolean] コンボボックスの開状態が変更されたときに呼び出されるイベントハンドラ。 |
update:searchTerm | [value: string] コンボボックスのsearchTermが変更されたときに呼び出されるイベントハンドラ。 |
update:selectedValue | [value: AcceptableValue] コンボボックスの強調表示された値が変更されたときに呼び出されるイベントハンドラ。 |
スロット (デフォルト) | ペイロード |
---|---|
open | boolean 現在の開状態 |
modelValue | AcceptableValue | AcceptableValue[] 現在の有効な値 |
アンカー
`ComboboxContent`の位置を`popper`に設定した場合、アンカーとして使用されます。
プロパティ | デフォルト | 型 |
---|---|---|
as | 'div' | AsTag | コンポーネント このコンポーネントがレンダリングされる要素またはコンポーネント。`asChild` で上書きできます。 |
asChild | boolean 子として渡された要素にデフォルトのレンダリング要素を変更し、それらのプロパティと動作をマージします。 詳細については、コンポジションガイドをご覧ください。 |
入力
コンボボックスの項目を検索するための入力コンポーネント。
プロパティ | デフォルト | 型 |
---|---|---|
as | 'input' | AsTag | コンポーネント このコンポーネントがレンダリングされる要素またはコンポーネント。`asChild` で上書きできます。 |
asChild | boolean 子として渡された要素にデフォルトのレンダリング要素を変更し、それらのプロパティと動作をマージします。 詳細については、コンポジションガイドをご覧ください。 | |
autoFocus | boolean マウント時に要素にフォーカスします。 | |
disabled | boolean `true`の場合、ユーザーが項目と対話できなくなります。 | |
type | 'text' | string ネイティブ入力タイプ |
トリガー
コンボボックスコンテンツを切り替えるボタン。
プロパティ | デフォルト | 型 |
---|---|---|
as | 'button' | AsTag | コンポーネント このコンポーネントがレンダリングされる要素またはコンポーネント。`asChild` で上書きできます。 |
asChild | boolean 子として渡された要素にデフォルトのレンダリング要素を変更し、それらのプロパティと動作をマージします。 詳細については、コンポジションガイドをご覧ください。 | |
disabled | boolean `true`の場合、ユーザーが項目と対話できなくなります。 |
データ属性 | 値 |
---|---|
[data-state] | "open" | "closed" |
[data-disabled] | 無効な場合に表示されます。 |
キャンセル
検索用語をクリアするボタン。
プロパティ | デフォルト | 型 |
---|---|---|
as | 'button' | AsTag | コンポーネント このコンポーネントがレンダリングされる要素またはコンポーネント。`asChild` で上書きできます。 |
asChild | boolean 子として渡された要素にデフォルトのレンダリング要素を変更し、それらのプロパティと動作をマージします。 詳細については、コンポジションガイドをご覧ください。 |
空
項目がクエリに一致しない場合に表示されます。
プロパティ | デフォルト | 型 |
---|---|---|
as | 'div' | AsTag | コンポーネント このコンポーネントがレンダリングされる要素またはコンポーネント。`asChild` で上書きできます。 |
asChild | boolean 子として渡された要素にデフォルトのレンダリング要素を変更し、それらのプロパティと動作をマージします。 詳細については、コンポジションガイドをご覧ください。 |
ポータル
使用する場合、コンテンツ部分を`body`にポータルします。
`ComboboxContent`の位置を`popper`に設定して、`Popover`または`DropdownMenu`と同様に位置が自動的に計算されるようにする必要があります。
プロパティ | デフォルト | 型 |
---|---|---|
disabled | boolean テレポートを無効にして、コンポーネントをインラインでレンダリングします。 | |
forceMount | boolean より多くの制御が必要な場合にマウントを強制するために使用します。Vueアニメーションライブラリでアニメーションを制御する場合に役立ちます。 | |
to | string | HTMLElement Vueネイティブテレポートコンポーネントプロパティ`:to` |
コンテンツ
コンボボックスが開いているときに表示されるコンポーネント。
プロパティ | デフォルト | 型 |
---|---|---|
align | 'start' | 'center' | 'end' トリガーに対する優先される配置。衝突が発生したときに変更される可能性があります。 | |
alignOffset | number `start`または`end`の配置オプションからのピクセル単位のオフセット。 | |
arrowPadding | number 矢印とコンテンツの端の間のパディング。コンテンツにborder-radiusがある場合、これにより角がオーバーフローするのを防ぎます。 | |
as | 'div' | AsTag | コンポーネント このコンポーネントがレンダリングされる要素またはコンポーネント。`asChild` で上書きできます。 |
asChild | boolean 子として渡された要素にデフォルトのレンダリング要素を変更し、それらのプロパティと動作をマージします。 詳細については、コンポジションガイドをご覧ください。 | |
avoidCollisions | boolean `true`の場合、境界線の端との衝突を防ぐために、sideとalignの設定を上書きします。 | |
bodyLock | boolean document.bodyがロックされ、スクロールが無効になります。 | |
collisionBoundary | Element | (Element | null)[] | null 衝突境界として使用される要素。デフォルトではビューポートですが、このチェックに含める追加の要素を提供できます。 | |
collisionPadding | number | Partial<Record<'top' | 'right' | 'bottom' | 'left', number>> 境界線の端から衝突検出が発生する距離(ピクセル単位)。数値(すべての辺で同じ)、または部分的なパディングオブジェクト(例:{ top: 20, left: 20 })を受け入れます。 | |
disableOutsidePointerEvents | boolean `true`の場合、`DismissableLayer`の外側の要素では、ホバー/フォーカス/クリック操作が無効になります。ユーザーは外側の要素と対話するために2回クリックする必要があります。1回目は`DismissableLayer`を閉じ、2回目は要素をトリガーします。 | |
dismissable | boolean コンポーネントをdismissableLayerにすることを許可します。 | |
forceMount | boolean より多くの制御が必要な場合にマウントを強制するために使用します。Vueアニメーションライブラリでアニメーションを制御する場合に役立ちます。 | |
hideWhenDetached | boolean トリガーが完全に隠れたときにコンテンツを隠すかどうか。 | |
position | 'inline' | 'popper' 使用する配置モード。 | |
prioritizePosition | boolean コンテンツをビューポート内に配置することを強制します。 参照要素と重なる可能性があり、望ましくない場合があります。 | |
side | 'top' | 'right' | 'bottom' | 'left' 開いているときにトリガーに対してレンダリングする優先側。衝突が発生し、avoidCollisionsが有効になっている場合、逆になります。 | |
sideOffset | number トリガーからの距離(ピクセル単位)。 | |
sticky | 'partial' | 'always' 整列軸のスティッキー動作。`partial`は、トリガーが境界内に少なくとも部分的にある限り、コンテンツを境界内に維持しますが、「always」は、境界内にあるかどうかに関係なく、コンテンツを境界内に維持します。 | |
updatePositionStrategy | 'always' | 'optimized' すべてのアニメーションフレームでフローティング要素の位置を更新する戦略。 |
Emit | ペイロード |
---|---|
escapeKeyDown | [event: KeyboardEvent] Escapeキーを押下した時に呼び出されるイベントハンドラです。キャンセル可能です。 |
focusOutside | [イベント: FocusOutsideEvent] フォーカスが |
interactOutside | [イベント: PointerDownOutsideEvent | FocusOutsideEvent]
|
pointerDownOutside | [イベント: PointerDownOutsideEvent]
|
データ属性 | 値 |
---|---|
[data-state] | "open" | "closed" |
[data-side] | "left" | "right" | "bottom" | "top" |
[data-align] | "start" | "end" | "center" |
CSS変数 | 説明 |
---|---|
--radix-combobox-content-transform-origin | コンテンツと矢印の位置/オフセットから計算された transform-origin です。position="popper" の場合のみ存在します。 |
--radix-combobox-content-available-width | トリガーと境界線の端の間の残りの幅です。 position="popper" の場合のみ存在します。 |
--radix-combobox-content-available-height | トリガーと境界線の端の間の残りの高さです。 position="popper" の場合のみ存在します。 |
--radix-combobox-trigger-width | トリガーの幅です。 position="popper" の場合のみ存在します。 |
--radix-combobox-trigger-height | トリガーの高さです。 position="popper" の場合のみ存在します。 |
ビューポート
すべてのアイテムを含むスクロール可能なビューポートです。
プロパティ | デフォルト | 型 |
---|---|---|
as | 'div' | AsTag | コンポーネント このコンポーネントがレンダリングされる要素またはコンポーネント。`asChild` で上書きできます。 |
asChild | boolean 子として渡された要素にデフォルトのレンダリング要素を変更し、それらのプロパティと動作をマージします。 詳細については、コンポジションガイドをご覧ください。 | |
nonce | string スタイルタグに |
アイテム
コンボボックスアイテムを含むコンポーネントです。
プロパティ | デフォルト | 型 |
---|---|---|
as | 'div' | AsTag | コンポーネント このコンポーネントがレンダリングされる要素またはコンポーネント。`asChild` で上書きできます。 |
asChild | boolean 子として渡された要素にデフォルトのレンダリング要素を変更し、それらのプロパティと動作をマージします。 詳細については、コンポジションガイドをご覧ください。 | |
disabled | boolean
| |
value* | AcceptableValue
|
Emit | ペイロード |
---|---|
select | [イベント: SelectEvent<AcceptableValue>] アイテムを選択した時に呼び出されるイベントハンドラです。 |
データ属性 | 値 |
---|---|
[data-state] | "checked" | "unchecked" |
[data-highlighted] | ハイライト表示されている場合に存在します。 |
[data-disabled] | 無効な場合に表示されます。 |
アイテムインジケーター
アイテムが選択された時にレンダリングされます。この要素を直接スタイル設定したり、アイコンを配置するためのラッパーとして使用したり、両方を使用したりできます。
プロパティ | デフォルト | 型 |
---|---|---|
as | 'span' | AsTag | コンポーネント このコンポーネントがレンダリングされる要素またはコンポーネント。`asChild` で上書きできます。 |
asChild | boolean 子として渡された要素にデフォルトのレンダリング要素を変更し、それらのプロパティと動作をマージします。 詳細については、コンポジションガイドをご覧ください。 |
グループ
複数のアイテムをグループ化するために使用します。アクセシビリティを確保するために、ComboboxLabel
と組み合わせて使用し、自動ラベル付けを行います。
プロパティ | デフォルト | 型 |
---|---|---|
as | 'div' | AsTag | コンポーネント このコンポーネントがレンダリングされる要素またはコンポーネント。`asChild` で上書きできます。 |
asChild | boolean 子として渡された要素にデフォルトのレンダリング要素を変更し、それらのプロパティと動作をマージします。 詳細については、コンポジションガイドをご覧ください。 |
ラベル
グループのラベルをレンダリングするために使用します。矢印キーではフォーカスできません。
プロパティ | デフォルト | 型 |
---|---|---|
as | 'div' | AsTag | コンポーネント このコンポーネントがレンダリングされる要素またはコンポーネント。`asChild` で上書きできます。 |
asChild | boolean 子として渡された要素にデフォルトのレンダリング要素を変更し、それらのプロパティと動作をマージします。 詳細については、コンポジションガイドをご覧ください。 | |
for | string |
セパレーター
コンボボックス内のアイテムを視覚的に区切るために使用します。
プロパティ | デフォルト | 型 |
---|---|---|
as | 'div' | AsTag | コンポーネント このコンポーネントがレンダリングされる要素またはコンポーネント。`asChild` で上書きできます。 |
asChild | boolean 子として渡された要素にデフォルトのレンダリング要素を変更し、それらのプロパティと動作をマージします。 詳細については、コンポジションガイドをご覧ください。 |
矢印
コンテンツと共にレンダリングするためのオプションの矢印要素です。これを使用して、トリガーとComboboxContent
を視覚的にリンクできます。ComboboxContent
内でレンダリングする必要があります。position
がpopper
に設定されている場合のみ使用できます。
プロパティ | デフォルト | 型 |
---|---|---|
as | 'svg' | AsTag | コンポーネント このコンポーネントがレンダリングされる要素またはコンポーネント。`asChild` で上書きできます。 |
asChild | boolean 子として渡された要素にデフォルトのレンダリング要素を変更し、それらのプロパティと動作をマージします。 詳細については、コンポジションガイドをご覧ください。 | |
height | 5 | number 矢印の高さをピクセル単位で指定します。 |
width | 10 | number 矢印の幅をピクセル単位で指定します。 |
例
オブジェクトを値としてバインドする
ネイティブのHTMLフォームコントロールは文字列のみを値として提供できますが、radix-vue
は複雑なオブジェクトもバインドできます。
アイテムを選択した際に入力値を設定するには、displayValue
プロップを設定してください。
<script setup lang="ts">
import { ref } from 'vue'
import { ComboboxContent, ComboboxInput, ComboboxItem, ComboboxPortal, ComboboxRoot } 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>
<ComboboxRoot
v-model="selectedPeople"
:display-value="(v) => v.name"
>
<ComboboxInput />
<ComboboxPortal>
<ComboboxContent>
<ComboboxItem
v-for="person in people"
:key="person.id"
:value="person"
:disabled="person.unavailable"
>
{{ person.name }}
</ComboboxItem>
</ComboboxContent>
</ComboboxPortal>
</ComboboxRoot>
</template>
複数の値を選択する
Combobox
コンポーネントでは、複数の値を選択できます。単一の値ではなく、値の配列を提供することで有効にできます。
<script setup lang="ts">
import { ref } from 'vue'
import { ComboboxRoot } 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>
<ComboboxRoot
v-model="selectedPeople"
multiple
>
...
</ComboboxRoot>
</template>
カスタムフィルタリング
内部的に、ComboboxRoot
は、関連するComboboxItem
をフィルタリングするためのデフォルトのフィルタ関数を適用します(modelValue
が文字列型の場合のみ適用されます)。
ただし、この動作は2つの異なる方法で置き換えることができます。
1. filter-function
プロップを提供する
<script setup lang="ts">
import { ref } from 'vue'
import { ComboboxContent, ComboboxInput, ComboboxItem, ComboboxPortal, ComboboxRoot } 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])
function filterFunction(list: typeof people[number], searchTerm: string) {
return list.filter((person) => {
return person.name.toLowerCase().includes(searchTerm.toLowerCase())
})
}
</script>
<template>
<ComboboxRoot
v-model="selectedPeople"
:filter-function="filterFunction"
>
<ComboboxInput />
<ComboboxPortal>
<ComboboxContent>
<ComboboxItem
v-for="person in people"
:key="person.id"
:value="person"
:disabled="person.unavailable"
>
{{ person.name }}
</ComboboxItem>
</ComboboxContent>
</ComboboxPortal>
</ComboboxRoot>
</template>
2. フィルタリングされたv-for
オプション
<script setup lang="ts">
import { ref } from 'vue'
import { ComboboxContent, ComboboxInput, ComboboxItem, ComboboxPortal, ComboboxRoot } 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>
<ComboboxRoot
v-model="selectedPeople"
v-model:searchTerm="searchTerm"
>
<ComboboxInput />
<ComboboxPortal>
<ComboboxContent>
<ComboboxItem
v-for="person in filteredPeople"
:key="person.id"
:value="person"
:disabled="person.unavailable"
>
{{ person.name }}
</ComboboxItem>
</ComboboxContent>
</ComboboxPortal>
</ComboboxRoot>
</template>
カスタムラベル
デフォルトでは、Combobox
は入力内容をスクリーンリーダーのラベルとして使用します。補助技術にアナウンスされる内容をより細かく制御する場合は、Labelコンポーネントを使用してください。
<script setup lang="ts">
import { ref } from 'vue'
import { ComboboxInput, ComboboxRoot, Label } from 'radix-vue'
</script>
<template>
<ComboboxRoot v-model="selectedPeople">
<Label for="person">Person: </Label>
<ComboboxInput
id="person"
placeholder="Select a person"
/>
...
</ComboboxRoot>
</template>
無効なアイテムを使用する場合
data-disabled
属性を使用して、無効なアイテムに特別なスタイルを追加できます。
<script setup lang="ts">
import { ref } from 'vue'
import {
ComboboxContent,
ComboboxInput,
ComboboxItem,
ComboboxPortal,
ComboboxRoot,
} from 'radix-vue'
</script>
<template>
<ComboboxRoot>
<ComboboxInput />
<ComboboxPortal>
<ComboboxContent>
<ComboboxItem
class="ComboboxItem"
disabled
>
...
</ComboboxItem>
</ComboboxContent>
</ComboboxPortal>
</ComboboxRoot>
</template>
/* styles.css */
.ComboboxItem[data-disabled] {
color: "gainsboro";
}
セパレーターを使用する場合
Separator
を使用して、アイテム間にセパレーターを追加します。
<script setup lang="ts">
import { ref } from 'vue'
import {
ComboboxContent,
ComboboxInput,
ComboboxItem,
ComboboxPortal,
ComboboxRoot,
ComboboxSeparator
} from 'radix-vue'
</script>
<template>
<ComboboxRoot>
<ComboboxInput />
<ComboboxPortal>
<ComboboxContent>
<ComboboxItem>…</ComboboxItem>
<ComboboxItem>…</ComboboxItem>
<ComboboxItem>…</ComboboxItem>
<ComboboxSeparator />
<ComboboxItem>…</ComboboxItem>
<ComboboxItem>…</ComboboxItem>
<ComboboxItem>…</ComboboxItem>
</ComboboxContent>
</ComboboxPortal>
</ComboboxRoot>
</template>
グループ化されたアイテムを使用する場合
Group
とLabel
を使用して、アイテムをセクションにグループ化します。
<script setup lang="ts">
import { ref } from 'vue'
import {
ComboboxContent,
ComboboxGroup,
ComboboxInput,
ComboboxItem,
ComboboxLabel,
ComboboxPortal,
ComboboxRoot
} from 'radix-vue'
</script>
<template>
<ComboboxRoot>
<ComboboxInput />
<ComboboxPortal>
<ComboboxContent>
<ComboboxGroup>
<ComboboxLabel>Label</ComboboxLabel>
<ComboboxItem>…</ComboboxItem>
<ComboboxItem>…</ComboboxItem>
<ComboboxItem>…</ComboboxItem>
</ComboboxGroup>
</ComboboxContent>
</ComboboxPortal>
</ComboboxRoot>
</template>
複雑なアイテムを使用する場合
アイテムにカスタムコンテンツを使用できます。
<script setup lang="ts">
import { ref } from 'vue'
import {
ComboboxContent,
ComboboxGroup,
ComboboxInput,
ComboboxItem,
ComboboxItemIndicator,
ComboboxLabel,
ComboboxPortal,
ComboboxRoot
} from 'radix-vue'
</script>
<template>
<ComboboxRoot>
<ComboboxInput />
<ComboboxPortal>
<ComboboxContent>
<ComboboxItem>
<img src="…">
Adolfo Hess
<ComboboxItemIndicator />
</ComboboxItem>
…
</ComboboxContent>
</ComboboxPortal>
</ComboboxRoot>
</template>
選択動作を防止する
デフォルトでは、ComboboxItem
を選択するとコンテンツが閉じ、提供された値でmodelValue
が更新されます。@select.prevent
でデフォルト動作をキャンセルできます。
<script setup lang="ts">
import { ref } from 'vue'
import { ComboboxContent, ComboboxGroup, ComboboxInput, ComboboxItem, ComboboxItemIndicator, ComboboxLabel, ComboboxPortal, ComboboxRoot } from 'radix-vue'
</script>
<template>
<ComboboxRoot>
<ComboboxInput />
<ComboboxPortal>
<ComboboxContent>
<ComboboxItem @select.prevent>
Item A
</ComboboxItem>
…
</ComboboxContent>
</ComboboxPortal>
</ComboboxRoot>
</template>
アクセシビリティ
コンボボックスWAI-ARIAデザインパターンに準拠しています。
詳細については、W3Cのコンボボックス自動補完リストの例を参照してください。
キーボード操作
キー | 説明 |
---|---|
Enter | ComboboxItem にフォーカスがある場合、フォーカスされているアイテムを選択します。 |
ArrowDown | ComboboxInput にフォーカスがある場合、コンボボックスコンテンツを開きます。アイテムにフォーカスがある場合、フォーカスを次のアイテムに移動します。 |
ArrowUp | ComboboxInput にフォーカスがある場合、コンボボックスコンテンツを開きます。アイテムにフォーカスがある場合、フォーカスを前のアイテムに移動します。 |
Esc | コンボボックスを閉じ、 ComboboxInput フィールドに選択されたアイテムを復元します。 |
カスタムAPI
プリミティブな部分を独自のコンポーネントに抽象化することで、独自のAPIを作成できます。
コマンドメニュー
コンボボックスを使用して、独自のコマンドメニューを作成できます。
使用方法
<script setup lang="ts">
import { Command, CommandItem } from './your-command'
</script>
<template>
<Command>
<CommandItem value="1">
Item 1
</CommandItem>
<CommandItem value="2">
Item 2
</CommandItem>
<CommandItem value="3">
Item 3
</CommandItem>
</Command>
</template>
実装
// your-command.ts
export { default as Command } from 'Command.vue'
export { default as CommandItem } from 'CommandItem.vue'
<!-- Command.vue -->
<script setup lang="ts">
import { CheckIcon, ChevronDownIcon, ChevronUpIcon, } from '@radix-icons/vue'
import { ComboboxContent, ComboboxEmpty, ComboboxInput, ComboboxPortal, ComboboxRoot, useForwardPropsEmits } from 'radix-vue'
import type { ComboboxRootEmits, ComboboxRootProps } from 'radix-vue'
const props = defineProps<ComboboxRootProps>()
const emits = defineEmits<ComboboxRootEmits>()
const forward = useForwardPropsEmits(props, emits)
</script>
<template>
<ComboboxRoot
v-bind="forward"
:open="true"
model-value=""
>
<ComboboxInput placeholder="Type a command or search..." />
<ComboboxPortal>
<ComboboxContent>
<ComboboxEmpty />
<ComboboxViewport>
<slot />
</ComboboxViewport>
</ComboboxContent>
</ComboboxPortal>
</ComboboxRoot>
</template>
<!-- ComboboxItem.vue -->
<script setup lang="ts">
import { CheckIcon } from '@radix-icons/vue'
import { ComboboxItem, type ComboboxItemProps } from 'radix-vue'
const props = defineProps<ComboboxItemProps>()
</script>
<template>
<ComboboxItem
v-bind="props"
@select.prevent
>
<slot />
</ComboboxItem>
</template>