ツリー
アルファ- コンポーザブル
- コンポーネント
- ホーム
- app.vue
- nuxt.config.ts
ディレクトリ構造
<script setup lang="ts">
import { TreeItem, TreeRoot } from 'radix-vue'
import { Icon } from '@iconify/vue'
const items = [
{
title: 'composables',
icon: 'lucide:folder',
children: [
{ title: 'useAuth.ts', icon: 'vscode-icons:file-type-typescript' },
{ title: 'useUser.ts', icon: 'vscode-icons:file-type-typescript' },
],
},
{
title: 'components',
icon: 'lucide:folder',
children: [
{
title: 'Home',
icon: 'lucide:folder',
children: [
{ title: 'Card.vue', icon: 'vscode-icons:file-type-vue' },
{ title: 'Button.vue', icon: 'vscode-icons:file-type-vue' },
],
},
],
},
{ title: 'app.vue', icon: 'vscode-icons:file-type-vue' },
{ title: 'nuxt.config.ts', icon: 'vscode-icons:file-type-nuxt' },
]
</script>
<template>
<TreeRoot
v-slot="{ flattenItems }"
class="list-none select-none w-56 bg-white text-blackA11 rounded-lg p-2 text-sm font-medium"
:items="items"
:get-key="(item) => item.title"
:default-expanded="['components']"
>
<h2 class="font-semibold !text-base text-blackA11 px-2 pt-1">
Directory Structure
</h2>
<TreeItem
v-for="item in flattenItems"
v-slot="{ isExpanded }"
:key="item._id"
:style="{ 'padding-left': `${item.level - 0.5}rem` }"
v-bind="item.bind"
class="flex items-center py-1 px-2 my-0.5 rounded outline-none focus:ring-grass8 focus:ring-2 data-[selected]:bg-grass4"
>
<template v-if="item.hasChildren">
<Icon
v-if="!isExpanded"
icon="lucide:folder"
class="h-4 w-4"
/>
<Icon
v-else
icon="lucide:folder-open"
class="h-4 w-4"
/>
</template>
<Icon
v-else
:icon="item.value.icon || 'lucide:file'"
class="h-4 w-4"
/>
<div class="pl-2">
{{ item.value.title }}
</div>
</TreeItem>
</TreeRoot>
</template>
機能
- 制御可能または非制御可能。
- フォーカスは完全に管理されています。
- フルキーボードナビゲーション。
- 右から左への方向をサポート。
- 複数選択をサポート。
- 異なる選択動作。
インストール
コマンドラインからコンポーネントをインストールします。
$ npm add radix-vue
構成
すべての部品をインポートして組み立てる。
<script setup>
import { TreeItem, TreeRoot, TreeVirtualizer } from 'radix-vue'
</script>
<template>
<TreeRoot>
<TreeItem />
<!-- or with virtual -->
<TreeVirtualizer>
<TreeItem />
</TreeVirtualizer>
</TreeRoot>
</template>
APIリファレンス
ルート
ツリーのすべての部分を包含。
プロパティ | デフォルト | 型 |
---|---|---|
as | 'ul' | AsTag | Component このコンポーネントがレンダリングされる要素またはコンポーネント。`asChild`で上書きできます。 |
asChild | boolean 子として渡された要素のデフォルトのレンダリング要素を変更し、それらのプロパティと動作をマージします。 詳細はコンポジションガイドをご覧ください。 | |
defaultExpanded | string[] 最初にレンダリングされたときの展開済みツリーの値。展開済みツリーの状態を制御する必要がない場合に使用します。 | |
defaultValue | Record<string, any> | Record<string, any>[] 最初にレンダリングされたときのツリーの値。ツリーの状態を制御する必要がない場合に使用します。 | |
dir | 'ltr' | 'rtl' 該当する場合のリストボックスの読み取り方向。 | |
disabled | boolean
| |
expanded | string[] 展開済みアイテムの制御された値。`v-model`でバインドできます。 | |
getKey* | (val: Record<string, any>) => string この関数は各アイテムのインデックスを受け取り、そのアイテムの一意なキーを返す必要があります。 | |
getChildren | (val: Record<string, any>) => Record<string, any>[] | undefined この関数は各アイテムのインデックスを受け取り、そのアイテムの子のリストを返す必要があります。 | |
items | Record<string, any>[] アイテムのリスト | |
modelValue | Record<string, any> | Record<string, any>[] ツリーの制御された値。`v-model`でバインドできます。 | |
multiple | boolean 複数のオプションを選択できるかどうか。 | |
propagateSelect | boolean
| |
selectionBehavior | 'toggle' | 'replace' | 'toggle' コレクションで複数選択をどのように動作させるか。 |
Emit | ペイロード |
---|---|
update:expanded | [val: string[]] |
update:modelValue | [val: Record<string, any>] 値が変更されたときに呼び出されるイベントハンドラー。 |
スロット (デフォルト) | ペイロード |
---|---|
flattenItems | FlattenedItem<Record<string, any>>[] |
modelValue | Record<string, any> | Record<string, any>[] |
expanded | string[] |
アイテム
アイテムコンポーネント。
プロパティ | デフォルト | 型 |
---|---|---|
as | 'li' | AsTag | Component このコンポーネントがレンダリングされる要素またはコンポーネント。`asChild`で上書きできます。 |
asChild | boolean 子として渡された要素のデフォルトのレンダリング要素を変更し、それらのプロパティと動作をマージします。 詳細はコンポジションガイドをご覧ください。 | |
level* | number 深さのレベル | |
value* | Record<string, any> このアイテムに与えられる値 |
Emit | ペイロード |
---|---|
select | [event: SelectEvent<Record<string, any>>] アイテムを選択したときに呼び出されるイベントハンドラー。 |
toggle | [event: ToggleEvent<Record<string, any>>] アイテムを選択したときに呼び出されるイベントハンドラー。 |
スロット (デフォルト) | ペイロード |
---|---|
isExpanded | boolean |
isSelected | boolean |
isIndeterminate | boolean | undefined |
handleToggle |
|
handleSelect |
|
データ属性 | 値 |
---|---|
[data-indent] | 数値 |
[data-expanded] | 展開されている場合に存在 |
[data-selected] | 選択されている場合に存在 |
仮想化コンテナ
リストの仮想化を実現するための仮想コンテナ。
プロパティ | デフォルト | 型 |
---|---|---|
estimateSize | number 各アイテムの推定サイズ(px単位) | |
textContent | ((item: Record<string, any>) => string) タイプアヘッド機能を実現するための各アイテムのテキストコンテンツ |
スロット (デフォルト) | ペイロード |
---|---|
item | FlattenedItem<Record<string, any>> |
例
複数アイテムの選択
Tree
コンポーネントを使用すると、複数のアイテムを選択できます。単一の値ではなく値の配列を提供することで、これを有効にできます。
<script setup lang="ts">
import { ref } from 'vue'
import { TreeRoot } 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>
<TreeRoot
v-model="selectedPeople"
multiple
>
...
</TreeRoot>
</template>
仮想リスト
長いアイテムリストをレンダリングするとアプリが遅くなる可能性があるため、仮想化を使用するとパフォーマンスが大幅に向上します。
<script setup lang="ts">
import { ref } from 'vue'
import { TreeItem, TreeRoot, TreeVirtualizer } from 'radix-vue'
</script>
<template>
<TreeRoot :items>
<!-- checkout https://radix-vue.com/components/tree.html#virtualizer -->
<TreeVirtualizer
v-slot="{ item }"
:text-content="(opt) => opt.name"
>
<TreeItem v-bind="item.bind">
{{ person.name }}
</TreeItem>
</TreeVirtualizer>
</TreeRoot>
</template>
チェックボックス付き
一部のTree
コンポーネントでは、トグル/中間
チェックボックスを表示したい場合があります。いくつかのプロパティとpreventDefault
イベントを使用することで、Tree
コンポーネントの動作を変更できます。
親のチェックボックスで子孫を選択/選択解除したいので、propagateSelect
をtrue
に設定します。次に、select
イベントをトリガーするチェックボックスを追加します。
<script setup lang="ts">
import { ref } from 'vue'
import { TreeItem, TreeRoot } from 'radix-vue'
</script>
<template>
<TreeRoot
v-slot="{ flattenItems }"
:items
multiple
propagate-select
>
<TreeItem
v-for="item in flattenItems"
:key="item._id"
v-bind="item.bind"
v-slot="{ handleSelect, isSelected, isIndeterminate }"
@select="(event) => {
if (event.detail.originalEvent.type === 'click')
event.preventDefault()
}"
@toggle="(event) => {
if (event.detail.originalEvent.type === 'keydown')
event.preventDefault()
}"
>
<Icon
v-if="item.hasChildren"
icon="radix-icons:chevron-down"
/>
<button
tabindex="-1"
@click.stop
@change="handleSelect"
>
<Icon
v-if="isSelected"
icon="radix-icons:check"
/>
<Icon
v-else-if="isIndeterminate"
icon="radix-icons:dash"
/>
<Icon
v-else
icon="radix-icons:box"
/>
</button>
<div class="pl-2">
{{ item.value.title }}
</div>
</TreeItem>
</TreeRoot>
</template>
ネストされたツリーノード
デフォルトの例では、フラットなツリーアイテムとノードが表示されます。これにより、仮想化やドラッグアンドドロップなどのカスタム機能が容易になります。ただし、ネストされたDOMノードを持つように構築することもできます。
Tree.vue
内では、
<script setup lang="ts">
import { TreeItem } from 'radix-vue'
interface TreeNode {
title: string
icon: string
children?: TreeNode[]
}
withDefaults(defineProps<{
treeItems: TreeNode[]
level?: number
}>(), { level: 0 })
</script>
<template>
<li
v-for=" tree in treeItems"
:key="tree.title"
>
<TreeItem
v-slot="{ isExpanded }"
as-child
:level="level"
:value="tree"
>
<button>…</button>
<ul v-if="isExpanded && tree.children">
<Tree
:tree-items="tree.children"
:level="level + 1"
/>
</ul>
</TreeItem>
</li>
</template>
CustomTree.vue
内では
<template>
<TreeRoot
:items="items"
:get-key="(item) => item.title"
>
<Tree :tree-items="items" />
</TreeRoot>
</template>
カスタム子スキーマ
デフォルトでは、<TreeRoot />
は、各ノードのchildren
のリストを渡すことで、ノードの子のリストを提供することを想定しています。`getChildren`プロパティを提供することで、それをオーバーライドできます。
::: 注記 ノードに子がない場合、getChildren
は空の配列ではなくundefined
を返す必要があります。::
<script setup lang="ts">
import { ref } from 'vue'
import { TreeRoot } from 'radix-vue'
interface FileNode {
title: string
icon: string
}
interface DirectoryNode {
title: string
icon: string
directories?: DirectoryNode[]
files?: FileNode[]
}
</script>
<template>
<TreeRoot
:items="items"
:get-key="(item) => item.title"
:get-children="(item) => (!item.files) ? item.directories : (!item.directories) ? item.files : [...item.directories, ...item.files]"
>
...
</TreeRoot>
</template>
ドラッグ可能/ソート可能なツリー
より複雑なドラッグ可能なTree
コンポーネントの場合、この例では、dndの処理のための主要なパッケージとしてpragmatic-drag-and-dropを使用します。
アクセシビリティ
キーボード操作
キー | 説明 |
---|---|
Enter | TreeItem をハイライト表示すると、フォーカスされているアイテムを選択します。 |
下矢印 | TreeItem にフォーカスがある場合、フォーカスを次のアイテムに移動します。 |
上矢印 | TreeItem にフォーカスがある場合、フォーカスを前のアイテムに移動します。 |
右矢印 | 閉じられた TreeItem (ノード)にフォーカスがある場合、フォーカスを移動せずにノードを開きます。開いているノードの場合、フォーカスを最初の子ノードに移動します。最後のノードの場合、何も行いません。 |
左矢印 | 開いている TreeItem (ノード)にフォーカスがある場合、ノードを閉じます。最後のノードまたは閉じられたノードでもある子ノードにフォーカスがある場合、フォーカスを親ノードに移動します。最後のノードまたは閉じられたノードでもあるルートノードにフォーカスがある場合、何も行いません。 |
HomePageUp | フォーカスを最初の TreeItem に移動します。 |
EndPageDown | フォーカスを最後の TreeItem に移動します。 |