セレクト
<script setup lang="ts">
import { Icon } from '@iconify/vue'
import { ref } from 'vue'
import {
SelectContent,
SelectGroup,
SelectItem,
SelectItemIndicator,
SelectItemText,
SelectLabel,
SelectPortal,
SelectRoot,
SelectScrollDownButton,
SelectScrollUpButton,
SelectSeparator,
SelectTrigger,
SelectValue,
SelectViewport,
} from 'radix-vue'
const fruit = ref()
const options = ['Apple', 'Banana', 'Blueberry', 'Grapes', 'Pineapple']
const vegetables = ['Aubergine', 'Broccoli', 'Carrot', 'Courgette', 'Leek']
</script>
<template>
<SelectRoot v-model="fruit">
<SelectTrigger
class="inline-flex min-w-[160px] 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-green9 outline-none"
aria-label="Customise options"
>
<SelectValue placeholder="Select a fruit..." />
<Icon
icon="radix-icons:chevron-down"
class="h-3.5 w-3.5"
/>
</SelectTrigger>
<SelectPortal>
<SelectContent
class="min-w-[160px] bg-white 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 z-[100]"
:side-offset="5"
>
<SelectScrollUpButton class="flex items-center justify-center h-[25px] bg-white text-violet11 cursor-default">
<Icon icon="radix-icons:chevron-up" />
</SelectScrollUpButton>
<SelectViewport class="p-[5px]">
<SelectLabel class="px-[25px] text-xs leading-[25px] text-mauve11">
Fruits
</SelectLabel>
<SelectGroup>
<SelectItem
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-green9 data-[highlighted]:text-green1"
:value="option"
>
<SelectItemIndicator class="absolute left-0 w-[25px] inline-flex items-center justify-center">
<Icon icon="radix-icons:check" />
</SelectItemIndicator>
<SelectItemText>
{{ option }}
</SelectItemText>
</SelectItem>
</SelectGroup>
<SelectSeparator class="h-[1px] bg-green6 m-[5px]" />
<SelectLabel class="px-[25px] text-xs leading-[25px] text-mauve11">
Vegetables
</SelectLabel>
<SelectGroup>
<SelectItem
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-green9 data-[highlighted]:text-green1"
:value="option"
:disabled="option === 'Courgette'"
>
<SelectItemIndicator class="absolute left-0 w-[25px] inline-flex items-center justify-center">
<Icon icon="radix-icons:check" />
</SelectItemIndicator>
<SelectItemText>
{{ option }}
</SelectItemText>
</SelectItem>
</SelectGroup>
</SelectViewport>
<SelectScrollDownButton class="flex items-center justify-center h-[25px] bg-white text-violet11 cursor-default">
<Icon icon="radix-icons:chevron-down" />
</SelectScrollDownButton>
</SelectContent>
</SelectPortal>
</SelectRoot>
</template>
特徴
- 制御付きまたは制御なしで使用できます。
- 2つのポジショニングモードを提供します。
- アイテム、ラベル、アイテムのグループをサポートします。
- フォーカスは完全に管理されています。
- 完全なキーボードナビゲーション。
- カスタムプレースホルダーをサポートします。
- タイプアヘッドをサポートします。
- 右から左への方向をサポートします。
インストール
コマンドラインからコンポーネントをインストールします。
$ npm add radix-vue
構造
すべてのパーツをインポートして組み合わせます。
<script setup lang="ts">
import {
SelectContent,
SelectGroup,
SelectItem,
SelectItemIndicator,
SelectLabel,
SelectPortal,
SelectRoot,
SelectScrollDownButton,
SelectScrollUpButton,
SelectSeparator,
SelectTrigger,
SelectValue,
SelectViewport,
} from 'radix-vue'
</script>
<template>
<SelectRoot>
<SelectTrigger>
<SelectValue />
<SelectIcon />
</SelectTrigger>
<SelectPortal>
<SelectContent>
<SelectScrollUpButton />
<SelectViewport>
<SelectItem>
<SelectItemText />
<SelectItemIndicator />
</SelectItem>
<SelectGroup>
<SelectLabel />
<SelectItem>
<SelectItemText />
<SelectItemIndicator />
</SelectItem>
</SelectGroup>
<SelectSeparator />
</SelectViewport>
<SelectScrollDownButton />
<SelectArrow />
</SelectContent>
</SelectPortal>
</SelectRoot>
</template>
APIリファレンス
ルート
セレクトのすべてのパーツが含まれます
プロパティ | デフォルト | 型 |
---|---|---|
autocomplete | string ネイティブのhtml入力 | |
defaultOpen | boolean 最初にレンダリングされたときのセレクトの開閉状態。開閉状態を制御する必要がない場合に使用します。 | |
defaultValue | '' | string 最初にレンダリングされたときのセレクトの値。セレクトの状態を制御する必要がない場合に使用します |
dir | 'ltr' | 'rtl' 該当する場合、コンボボックスの読み取り方向。 | |
disabled | boolean
| |
modelValue | string セレクトの制御された値。 | |
name | string セレクトの名前。名前と値のペアの一部として、所有するフォームとともに送信されます。 | |
open | boolean セレクトの制御された開閉状態。 | |
required | boolean
|
イベント | ペイロード |
---|---|
update:modelValue | [value: string] 値が変更されたときに呼び出されるイベントハンドラー。 |
update:open | [value: boolean] コンテキストメニューの開閉状態が変更されたときに呼び出されるイベントハンドラー。 |
スロット(デフォルト) | ペイロード |
---|---|
modelValue | string 現在の入力値 |
open | boolean 現在の開閉状態 |
トリガー
セレクトを切り替えるボタン。SelectContent
は、トリガー上に整列して配置されます。
プロパティ | デフォルト | 型 |
---|---|---|
as | 'button' | AsTag | Component このコンポーネントがレンダリングされる要素またはコンポーネント。 |
asChild | boolean 子として渡された要素のデフォルトのレンダリング要素を変更し、それらのプロパティと動作をマージします。 詳細については、コンポジションガイドをお読みください。 | |
disabled | boolean |
データ属性 | 値 |
---|---|
[data-state] | "open" | "closed" |
[data-disabled] | 無効の場合に存在します |
[data-placeholder] | プレースホルダーがある場合に存在します |
値
選択された値を反映する部分。デフォルトでは、選択されたアイテムのテキストがレンダリングされます。より詳細な制御が必要な場合は、代わりにセレクトを制御し、独自のchildren
を渡すことができます。正しいポジショニングを確保するために、スタイルを設定しないでください。セレクトに値がない場合のために、オプションのplaceholder
プロパティも使用できます。
プロパティ | デフォルト | 型 |
---|---|---|
as | 'span' | AsTag | Component このコンポーネントがレンダリングされる要素またはコンポーネント。 |
asChild | boolean 子として渡された要素のデフォルトのレンダリング要素を変更し、それらのプロパティと動作をマージします。 詳細については、コンポジションガイドをお読みください。 | |
placeholder | '' | string
|
アイコン
開くことができるという事実を視覚的に示すためによく値の横に表示される小さなアイコン。デフォルトでは▼をレンダリングしますが、asChild
またはchildren
を使用して独自のアイコンを使用できます。
プロパティ | デフォルト | 型 |
---|---|---|
as | 'div' | AsTag | Component このコンポーネントがレンダリングされる要素またはコンポーネント。 |
asChild | boolean 子として渡された要素のデフォルトのレンダリング要素を変更し、それらのプロパティと動作をマージします。 詳細については、コンポジションガイドをお読みください。 | |
disabled | boolean
| |
textValue | string タイプアヘッドの目的で使用されるオプションのテキスト。 デフォルトでは、タイプアヘッドの動作は コンテンツが複雑な場合、または内部にテキスト以外のコンテンツがある場合は、これを使用してください。 | |
value* | string
|
ポータル
使用すると、コンテンツ部分がbody
にポータルされます。
プロパティ | デフォルト | 型 |
---|---|---|
disabled | boolean テレポーテーションを無効にして、コンポーネントをインラインでレンダリングします | |
forceMount | boolean より多くの制御が必要な場合に、強制的にマウントするために使用されます。Vueアニメーションライブラリでアニメーションを制御する場合に役立ちます。 | |
to | string | HTMLElement Vueネイティブのテレポーテーションコンポーネントのプロパティ |
コンテンツ
セレクトが開いているときにポップアップ表示されるコンポーネント。
プロパティ | デフォルト | 型 |
---|---|---|
align | 'start' | 'center' | 'end' トリガーに対する推奨される配置。衝突が発生すると変更される場合があります。 | |
alignOffset | number
| |
arrowPadding | number 矢印とコンテンツの端の間のパディング。コンテンツにborder-radiusがある場合、これにより角からはみ出さないようにします。 | |
as | 'div' | AsTag | Component このコンポーネントがレンダリングされる要素またはコンポーネント。 |
asChild | boolean 子として渡された要素のデフォルトのレンダリング要素を変更し、それらのプロパティと動作をマージします。 詳細については、コンポジションガイドをお読みください。 | |
avoidCollisions | boolean
| |
bodyLock | boolean document.bodyがロックされ、スクロールが無効になります。 | |
collisionBoundary | Element | (Element | null)[] | null 衝突境界として使用される要素。デフォルトではこれはビューポートですが、このチェックに含める追加の要素を指定できます。 | |
collisionPadding | number | Partial<Record<'top' | 'right' | 'bottom' | 'left', number>> 衝突検出が発生する境界エッジからのピクセル単位の距離。数値(すべての辺で同じ)または部分的なパディングオブジェクト(例:{ top: 20, left: 20 })を受け入れます。 | |
forceMount | boolean より多くの制御が必要な場合に、強制的にマウントするために使用されます。Vueアニメーションライブラリでアニメーションを制御する場合に役立ちます。 | |
hideWhenDetached | boolean トリガーが完全に隠れたときにコンテンツを非表示にするかどうか。 | |
position | 'popper' | 'item-aligned' 使用する位置調整モード
| |
prioritizePosition | boolean コンテンツをビューポート内に強制的に配置します。 参照要素と重なる可能性があり、望ましくない場合があります。 | |
side | 'top' | 'right' | 'bottom' | 'left' 開いたときにレンダリングするトリガーの優先側。衝突が発生し、avoidCollisionsが有効になっている場合は反転されます。 | |
sideOffset | number トリガーからのピクセル単位の距離。 | |
sticky | 'partial' | 'always' アライン軸での固定動作。 | |
updatePositionStrategy | 'always' | 'optimized' アニメーションフレームごとに浮動要素の位置を更新する戦略。 |
イベント | ペイロード |
---|---|
closeAutoFocus | [event: Event] クローズ時に自動フォーカスされるときに呼び出されるイベントハンドラー。キャンセル可能です。 |
escapeKeyDown | [event: KeyboardEvent] エスケープキーが押されたときに呼び出されるイベントハンドラー。キャンセル可能です。 |
pointerDownOutside | [event: PointerDownOutsideEvent]
|
データ属性 | 値 |
---|---|
[data-state] | "open" | "closed" |
[data-side] | "left" | "right" | "bottom" | "top" |
[data-align] | "start" | "end" | "center" |
CSS変数 | 説明 |
---|---|
--radix-select-content-transform-origin | コンテンツと矢印の位置/オフセットから計算された transform-origin 。position="popper" の場合にのみ存在します。 |
--radix-select-content-available-width | トリガーと境界エッジの間の残りの幅。 position="popper" の場合にのみ存在します。 |
--radix-select-content-available-height | トリガーと境界エッジの間の残りの高さ。 position="popper" の場合にのみ存在します。 |
--radix-select-trigger-width | トリガーの幅。 position="popper" の場合にのみ存在します。 |
--radix-select-trigger-height | トリガーの高さ。 position="popper" の場合にのみ存在します。 |
Viewport
すべてのアイテムを含むスクロールビューポート。
プロパティ | デフォルト | 型 |
---|---|---|
as | 'div' | AsTag | Component このコンポーネントがレンダリングされる要素またはコンポーネント。 |
asChild | boolean 子として渡された要素のデフォルトのレンダリング要素を変更し、それらのプロパティと動作をマージします。 詳細については、コンポジションガイドをお読みください。 | |
nonce | string コンテンツセキュリティポリシーで使用できる |
Item
選択アイテムを含むコンポーネント。
プロパティ | デフォルト | 型 |
---|---|---|
as | 'div' | AsTag | Component このコンポーネントがレンダリングされる要素またはコンポーネント。 |
asChild | boolean 子として渡された要素のデフォルトのレンダリング要素を変更し、それらのプロパティと動作をマージします。 詳細については、コンポジションガイドをお読みください。 | |
disabled | boolean
| |
textValue | string タイプアヘッドの目的で使用されるオプションのテキスト。 デフォルトでは、タイプアヘッドの動作は コンテンツが複雑な場合、または内部にテキスト以外のコンテンツがある場合は、これを使用してください。 | |
value* | string
|
データ属性 | 値 |
---|---|
[data-state] | "checked" | "unchecked" |
[data-highlighted] | ハイライト時に存在します |
[data-disabled] | 無効の場合に存在します |
ItemText
アイテムのテキスト部分。そのアイテムが選択されたときにトリガーに表示したいテキストのみを含める必要があります。正しい配置を確保するためにスタイルを設定しないでください。
プロパティ | デフォルト | 型 |
---|---|---|
as | 'span' | AsTag | Component このコンポーネントがレンダリングされる要素またはコンポーネント。 |
asChild | boolean 子として渡された要素のデフォルトのレンダリング要素を変更し、それらのプロパティと動作をマージします。 詳細については、コンポジションガイドをお読みください。 |
ItemIndicator
アイテムが選択されているときにレンダリングします。この要素に直接スタイルを設定することも、アイコンを入れるためのラッパーとして使用することも、両方行うこともできます。
プロパティ | デフォルト | 型 |
---|---|---|
as | 'span' | AsTag | Component このコンポーネントがレンダリングされる要素またはコンポーネント。 |
asChild | boolean 子として渡された要素のデフォルトのレンダリング要素を変更し、それらのプロパティと動作をマージします。 詳細については、コンポジションガイドをお読みください。 |
ScrollUpButton
ビューポートのオーバーフローを表示し、上方向へのスクロールを機能的に有効にするためのアフォーダンスとして使用されるオプションのボタン。
プロパティ | デフォルト | 型 |
---|---|---|
as | 'div' | AsTag | Component このコンポーネントがレンダリングされる要素またはコンポーネント。 |
asChild | boolean 子として渡された要素のデフォルトのレンダリング要素を変更し、それらのプロパティと動作をマージします。 詳細については、コンポジションガイドをお読みください。 |
ScrollDownButton
ビューポートのオーバーフローを表示し、下方向へのスクロールを機能的に有効にするためのアフォーダンスとして使用されるオプションのボタン。
プロパティ | デフォルト | 型 |
---|---|---|
as | 'div' | AsTag | Component このコンポーネントがレンダリングされる要素またはコンポーネント。 |
asChild | boolean 子として渡された要素のデフォルトのレンダリング要素を変更し、それらのプロパティと動作をマージします。 詳細については、コンポジションガイドをお読みください。 |
Group
複数のアイテムをグループ化するために使用します。自動ラベリングによって優れたアクセシビリティを確保するために SelectLabel
と組み合わせて使用します。
プロパティ | デフォルト | 型 |
---|---|---|
as | 'div' | AsTag | Component このコンポーネントがレンダリングされる要素またはコンポーネント。 |
asChild | boolean 子として渡された要素のデフォルトのレンダリング要素を変更し、それらのプロパティと動作をマージします。 詳細については、コンポジションガイドをお読みください。 |
Label
グループのラベルをレンダリングするために使用します。矢印キーを使用してフォーカスすることはできません。
プロパティ | デフォルト | 型 |
---|---|---|
as | 'div' | AsTag | Component このコンポーネントがレンダリングされる要素またはコンポーネント。 |
asChild | boolean 子として渡された要素のデフォルトのレンダリング要素を変更し、それらのプロパティと動作をマージします。 詳細については、コンポジションガイドをお読みください。 | |
for | string |
Separator
Select内のアイテムを視覚的に区切るために使用します
プロパティ | デフォルト | 型 |
---|---|---|
as | 'div' | AsTag | Component このコンポーネントがレンダリングされる要素またはコンポーネント。 |
asChild | boolean 子として渡された要素のデフォルトのレンダリング要素を変更し、それらのプロパティと動作をマージします。 詳細については、コンポジションガイドをお読みください。 |
Arrow
コンテンツと一緒にレンダリングするオプションの矢印要素。これは、トリガーと SelectContent
を視覚的にリンクするのに役立ちます。SelectContent
内でレンダリングする必要があります。position
が popper
に設定されている場合にのみ使用できます。
プロパティ | デフォルト | 型 |
---|---|---|
as | 'svg' | AsTag | Component このコンポーネントがレンダリングされる要素またはコンポーネント。 |
asChild | boolean 子として渡された要素のデフォルトのレンダリング要素を変更し、それらのプロパティと動作をマージします。 詳細については、コンポジションガイドをお読みください。 | |
height | 5 | number ピクセル単位の矢印の高さ。 |
width | 10 | number ピクセル単位の矢印の幅。 |
Examples
Change the positioning mode
デフォルトでは、Select
は、アクティブなアイテムを基準に SelectContent
を配置することで、ネイティブのMacOSメニューと同様に動作します。Popover
または DropdownMenu
と同様の代替の配置方法を優先する場合は、position
を popper
に設定し、side
、sideOffset
などの追加の配置オプションを使用できます。
// index.vue
<script setup lang="ts">
import {
SelectContent,
SelectGroup,
SelectItem,
SelectItemIndicator,
SelectLabel,
SelectPortal,
SelectRoot,
SelectSeparator,
SelectTrigger,
} from 'radix-vue'
</script>
<template>
<SelectRoot>
<SelectTrigger>…</SelectTrigger>
<SelectPortal>
<SelectContent
position="popper"
:side-offset="5"
>
…
</SelectContent>
</SelectPortal>
</SelectRoot>
</template>
Constrain the content size
SelectContent
で position="popper"
を使用する場合、コンテンツの幅をトリガーの幅に一致するように制約したい場合があります。また、高さをビューポートを超えないように制約することもできます。
これをサポートするために、--radix-select-trigger-width
や --radix-select-content-available-height
など、いくつかのCSSカスタムプロパティを公開しています。コンテンツのサイズを制約するために使用します。
// index.vue
<script setup lang="ts">
import {
SelectContent,
SelectGroup,
SelectItem,
SelectItemIndicator,
SelectLabel,
SelectPortal,
SelectRoot,
SelectSeparator,
SelectTrigger,
} from 'radix-vue'
</script>
<template>
<SelectRoot>
<SelectTrigger>…</SelectTrigger>
<SelectPortal>
<SelectContent
class="SelectContent"
position="popper"
:side-offset="5"
>
…
</SelectContent>
</SelectPortal>
</SelectRoot>
</template>
/* styles.css */
.SelectContent {
width: var(--radix-select-trigger-width);
max-height: var(--radix-select-content-available-height);
}
With disabled items
data-disabled
属性を使用して、無効なアイテムに特別なスタイルを追加できます。
// index.vue
<script setup lang="ts">
import {
SelectContent,
SelectGroup,
SelectItem,
SelectItemIndicator,
SelectLabel,
SelectPortal,
SelectRoot,
SelectSeparator,
SelectTrigger,
} from 'radix-vue'
</script>
<template>
<SelectRoot>
<SelectTrigger>…</SelectTrigger>
<SelectPortal>
<SelectContent>
<SelectViewport>
<SelectItem
class="SelectItem"
disabled
>
…
</SelectItem>
<SelectItem>…</SelectItem>
<SelectItem>…</SelectItem>
</SelectViewport>
</SelectContent>
</SelectPortal>
</SelectRoot>
</template>
/* styles.css */
.SelectItem[data-disabled] {
color: "gainsboro";
}
With a placeholder
selectに値がない場合は、Value
の placeholder
プロパティを使用できます。スタイリングに役立つ Trigger
の data-placeholder
属性もあります。
// index.vue
<script setup lang="ts">
import {
SelectContent,
SelectGroup,
SelectItem,
SelectItemIndicator,
SelectLabel,
SelectPortal,
SelectRoot,
SelectSeparator,
SelectTrigger,
} from 'radix-vue'
import './styles.css'
</script>
<template>
<SelectRoot>
<SelectTrigger class="SelectTrigger">
<SelectValue placeholder="Pick an option" />
<SelectIcon />
</SelectTrigger>
<SelectPortal>
<SelectContent>…</SelectContent>
</SelectPortal>
</SelectRoot>
</template>
/* styles.css */
.SelectTrigger[data-placeholder] {
color: "gainsboro";
}
With separators
アイテム間に区切りを追加するには、Separator
パーツを使用します。
<template>
<SelectRoot>
<SelectTrigger>…</SelectTrigger>
<SelectPortal>
<SelectContent>
<SelectViewport>
<SelectItem>…</SelectItem>
<SelectItem>…</SelectItem>
<SelectItem>…</SelectItem>
<SelectSeparator />
<SelectItem>…</SelectItem>
<SelectItem>…</SelectItem>
</SelectViewport>
</SelectContent>
</SelectPortal>
</SelectRoot>
</template>
With grouped items
セクション内のアイテムをグループ化するには、Group
および Label
パーツを使用します。
<template>
<SelectRoot>
<SelectTrigger>…</SelectTrigger>
<SelectPortal>
<SelectContent>
<SelectViewport>
<SelectGroup>
<SelectLabel>Label</SelectLabel>
<SelectItem>…</SelectItem>
<SelectItem>…</SelectItem>
<SelectItem>…</SelectItem>
</SelectGroup>
</SelectViewport>
</SelectContent>
</SelectPortal>
</SelectRoot>
</template>
With complex items
アイテムでカスタムコンテンツを使用できます。
<script setup lang="ts">
import {
SelectContent,
SelectGroup,
SelectItem,
SelectItemIndicator,
SelectLabel,
SelectPortal,
SelectRoot,
SelectSeparator,
SelectTrigger,
} from 'radix-vue'
</script>
<template>
<SelectRoot>
<SelectTrigger>…</SelectTrigger>
<SelectPortal>
<SelectContent>
<SelectViewport>
<SelectItem>
<SelectItemText>
<img src="…">
Adolfo Hess
</SelectItemText>
<SelectItemIndicator>…</SelectItemIndicator>
</SelectItem>
<SelectItem>…</SelectItem> <SelectItem>…</SelectItem>
</SelectViewport>
</SelectContent>
</SelectPortal>
</SelectRoot>
</template>
Controlling the value displayed in the trigger
デフォルトでは、トリガーには選択されたアイテムの ItemText
のコンテンツが自動的に表示されます。ItemText
パーツの内側/外側に配置するものを選択することで、表示されるものを制御できます。
より柔軟性が必要な場合は、v-model
プロパティを使用してコンポーネントを制御し、slot
を SelectValue
に渡すことができます。そこに配置するものがアクセス可能であることを確認してください。
<script setup>
const countries = { 'france': '🇫🇷', 'united-kingdom': '🇬🇧', 'spain': '🇪🇸' }
const value = ref('france')
</script>
<template>
<SelectRoot v-model="value">
<SelectTrigger>
<SelectValue aria-label="value">
{{ countries[value] }}
</SelectValue>
<SelectIcon />
</SelectTrigger>
<SelectPortal>
<SelectContent>
<SelectViewport>
<SelectItem value="france">
<SelectItemText>France</SelectItemText>
<SelectItemIndicator>…</SelectItemIndicator>
</SelectItem>
<SelectItem value="united-kingdom">
<SelectItemText>United Kingdom</SelectItemText>
<SelectItemIndicator>…</SelectItemIndicator>
</SelectItem>
<SelectItem value="spain">
<SelectItemText>Spain</SelectItemText>
<SelectItemIndicator>…</SelectItemIndicator>
</SelectItem>
</SelectViewport>
</SelectContent>
</SelectPortal>
</SelectRoot>
</template>
With custom scrollbar
最適なUXのために ScrollUpButton
および ScrollDownButton
パーツを使用することをお勧めするため、ネイティブのスクロールバーはデフォルトで非表示になっています。これらのパーツを使用したくない場合は、Scroll Area プリミティブを使用して select を構成します。
// index.vue
<script setup lang="ts">
import {
ScrollAreaRoot,
ScrollAreaScrollbar,
ScrollAreaThumb,
ScrollAreaViewport,
SelectContent,
SelectGroup,
SelectItem,
SelectItemIndicator,
SelectLabel,
SelectPortal,
SelectRoot,
SelectSeparator,
SelectTrigger,
} from 'radix-vue'
</script>
<template>
<SelectRoot>
<SelectTrigger>…</SelectTrigger>
<SelectPortal>
<SelectContent>
<ScrollAreaRoot
class="ScrollAreaRoot"
type="auto"
>
<SelectViewport as-child>
<ScrollAreaViewport class="ScrollAreaViewport">
<StyledItem>…</StyledItem> <StyledItem>…</StyledItem>
<StyledItem>…</StyledItem>
</ScrollAreaViewport>
</SelectViewport>
<ScrollAreaScrollbar
class="ScrollAreaScrollbar"
orientation="vertical"
>
<ScrollAreaThumb class="ScrollAreaThumb" />
</ScrollAreaScrollbar>
</ScrollAreaRoot>
</SelectContent>
</SelectPortal>
</SelectRoot>
</template>
/* styles.css */
.ScrollAreaRoot {
width: 100%;
height: 100%;
}
.ScrollAreaViewport {
width: 100%;
height: 100%;
}
.ScrollAreaScrollbar {
width: 4px;
padding: 5px 2px;
}
.ScrollAreaThumb {
background: rgba(0, 0, 0, 0.3);
borderradius: 3px;
}
Accessibility
ListBox WAI-ARIA デザインパターンに準拠しています。
詳細については、W3C Select-Only Combobox の例を参照してください。
Keyboard Interactions
キー | 説明 |
---|---|
スペース | フォーカスが SelectTrigger にある場合、select を開き、選択されたアイテムにフォーカスを合わせます。フォーカスがアイテムにある場合、フォーカスされたアイテムを選択します。 |
Enter | フォーカスが SelectTrigger にある場合、select を開き、最初のアイテムにフォーカスを合わせます。フォーカスがアイテムにある場合、フォーカスされたアイテムを選択します。 |
ArrowDown | フォーカスが SelectTrigger にある場合、Select を開きますフォーカスがアイテムにある場合、フォーカスを次のアイテムに移動します。 |
ArrowUp | フォーカスが SelectTrigger にある場合、Select を開きますフォーカスがアイテムにある場合、フォーカスを前のアイテムに移動します。 |
Esc | select を閉じ、フォーカスを SelectTrigger に移動します。 |
Labelling
Select の視覚的でアクセス可能なラベルを提供するには、Label コンポーネントを使用します
<script setup lang="ts">
import { Icon } from '@iconify/vue'
import { ref } from 'vue'
import {
Label,
SelectContent,
SelectGroup,
SelectItem,
SelectItemIndicator,
SelectLabel,
SelectPortal,
SelectRoot,
SelectSeparator,
SelectTrigger,
} from 'radix-vue'
</script>
<template>
<Label>
Country
<SelectRoot>…</SelectRoot>
</Label>
<!-- or -->
<Label for="country">Country</Label>
<SelectRoot>
<SelectTrigger id="country">
…
</SelectTrigger>
<SelectPortal>
<SelectContent>…</SelectContent>
</SelectPortal>
</SelectRoot>
</template>
Custom APIs
プリミティブパーツを独自のコンポーネントに抽象化することで、独自のAPIを作成します。
Abstract down to Select
and SelectItem
この例では、ほとんどのパーツを抽象化しています。
Usage
<script setup lang="ts">
import { Select, SelectItem } from './your-select'
</script>
<template>
<Select default-value="2">
<SelectItem value="1">
Item 1
</SelectItem>
<SelectItem value="2">
Item 2
</SelectItem>
<SelectItem value="3">
Item 3
</SelectItem>
</Select>
</template>
Implementation
// your-select.ts
export { default as Select } from 'Select.vue'
export { default as SelectItem } from 'SelectItem.vue'
<!-- Select.vue -->
<script setup lang="ts">
import { CheckIcon, ChevronDownIcon, ChevronUpIcon, } from '@radix-icons/vue'
import { SelectContent, SelectIcon, SelectPortal, SelectRoot, SelectScrollDownButton, SelectScrollUpButton, SelectTrigger, SelectValue, SelectViewport, useForwardPropsEmits } from 'radix-vue'
import type { SelectRootEmits, SelectRootProps } from 'radix-vue'
const props = defineProps<SelectRootProps>()
const emits = defineEmits<SelectRootEmits>()
const forward = useForwardPropsEmits(props, emits)
</script>
<template>
<SelectRoot v-bind="forward">
<SelectTrigger>
<SelectValue />
<SelectIcon>
<ChevronDownIcon />
</SelectIcon>
</SelectTrigger>
<SelectPortal>
<SelectContent>
<SelectScrollUpButton>
<ChevronUpIcon />
</SelectScrollUpButton>
<SelectViewport>
<slot />
</SelectViewport>
<SelectScrollDownButton>
<ChevronDownIcon />
</SelectScrollDownButton>
</SelectContent>
</SelectPortal>
</SelectRoot>
</template>
<!-- SelectItem.vue -->
<script setup lang="ts">
import { CheckIcon } from '@radix-icons/vue'
import { SelectItem, SelectItemIndicator, type SelectItemProps, SelectItemText } from 'radix-vue'
const props = defineProps<SelectItemProps>()
</script>
<template>
<SelectItem v-bind="props">
<SelectItemText>
<slot />
</SelectItemText>
<SelectItemIndicator>
<CheckIcon />
</SelectItemIndicator>
</SelectItem>
</template>