Vitral 0.2
Form

TreeSelect

A select over a tree, with the same filter and checkbox selection as Tree.

Import

main.ts
import { TreeSelect } from '@vitral/vue';

Basic

Value: null
<script setup lang="ts">import { Label, StackPanel, TreeSelect, type TreeNode } from '@vitral/vue';import { ref } from 'vue'; const files: TreeNode[] = [    {        key: 'docs',        label: 'Documents',        icon: 'folder',        children: [            { key: 'work', label: 'Work', icon: 'folder', children: [{ key: 'report', label: 'Relatório.pdf', icon: 'file' }, { key: 'budget', label: 'Budget.xlsx', icon: 'file' }] },            { key: 'home', label: 'Home', icon: 'folder', children: [{ key: 'recipes', label: 'Recipes.txt', icon: 'file' }] }        ]    },    { key: 'pics', label: 'Pictures', icon: 'folder', children: [{ key: 'trip', label: 'Trip to Évora.jpg', icon: 'file' }, { key: 'cat', label: 'Cat.png', icon: 'file' }] },    { key: 'notes', label: 'Notes.md', icon: 'file' }]; const single = ref<Record<string, boolean> | null>(null);</script> <template>    <StackPanel spacing="0.375rem" style="min-width: 16rem">        <Label for="ts-single">File</Label>        <TreeSelect id="ts-single" v-model="single" :options="files" placeholder="Select a file" show-clear />        <small style="color: var(--vt-text-muted-color)">Value: {{ JSON.stringify(single) }}</small>    </StackPanel></template>

Checkboxes and chips

<script setup lang="ts">import { Label, StackPanel, TreeSelect, type TreeNode } from '@vitral/vue';import { ref } from 'vue'; const files: TreeNode[] = [    {        key: 'docs',        label: 'Documents',        icon: 'folder',        children: [            { key: 'work', label: 'Work', icon: 'folder', children: [{ key: 'report', label: 'Relatório.pdf', icon: 'file' }, { key: 'budget', label: 'Budget.xlsx', icon: 'file' }] },            { key: 'home', label: 'Home', icon: 'folder', children: [{ key: 'recipes', label: 'Recipes.txt', icon: 'file' }] }        ]    },    { key: 'pics', label: 'Pictures', icon: 'folder', children: [{ key: 'trip', label: 'Trip to Évora.jpg', icon: 'file' }, { key: 'cat', label: 'Cat.png', icon: 'file' }] },    { key: 'notes', label: 'Notes.md', icon: 'file' }]; const checked = ref<Record<string, { checked: boolean; partialChecked: boolean }> | null>({ trip: { checked: true, partialChecked: false } });</script> <template>    <StackPanel spacing="0.375rem" style="min-width: 22rem">        <Label for="ts-check">Files</Label>        <TreeSelect id="ts-check" v-model="checked" :options="files" selection-mode="checkbox" display="chip" :max-selected-labels="4" fluid placeholder="Select files" />    </StackPanel></template>

Filter and multiple

<script setup lang="ts">import { Label, StackPanel, TreeSelect, type TreeNode } from '@vitral/vue';import { ref } from 'vue'; const files: TreeNode[] = [    {        key: 'docs',        label: 'Documents',        icon: 'folder',        children: [            { key: 'work', label: 'Work', icon: 'folder', children: [{ key: 'report', label: 'Relatório.pdf', icon: 'file' }, { key: 'budget', label: 'Budget.xlsx', icon: 'file' }] },            { key: 'home', label: 'Home', icon: 'folder', children: [{ key: 'recipes', label: 'Recipes.txt', icon: 'file' }] }        ]    },    { key: 'pics', label: 'Pictures', icon: 'folder', children: [{ key: 'trip', label: 'Trip to Évora.jpg', icon: 'file' }, { key: 'cat', label: 'Cat.png', icon: 'file' }] },    { key: 'notes', label: 'Notes.md', icon: 'file' }]; const many = ref(null);</script> <template>    <StackPanel spacing="0.375rem" style="min-width: 16rem">        <Label for="ts-filter">Files</Label>        <TreeSelect id="ts-filter" v-model="many" :options="files" selection-mode="multiple" filter placeholder="Search files" />    </StackPanel></template>

Sizes and states

<script setup lang="ts">import { TreeSelect, type TreeNode } from '@vitral/vue'; const files: TreeNode[] = [    {        key: 'docs',        label: 'Documents',        icon: 'folder',        children: [            { key: 'work', label: 'Work', icon: 'folder', children: [{ key: 'report', label: 'Relatório.pdf', icon: 'file' }, { key: 'budget', label: 'Budget.xlsx', icon: 'file' }] },            { key: 'home', label: 'Home', icon: 'folder', children: [{ key: 'recipes', label: 'Recipes.txt', icon: 'file' }] }        ]    },    { key: 'pics', label: 'Pictures', icon: 'folder', children: [{ key: 'trip', label: 'Trip to Évora.jpg', icon: 'file' }, { key: 'cat', label: 'Cat.png', icon: 'file' }] },    { key: 'notes', label: 'Notes.md', icon: 'file' }];</script> <template>    <TreeSelect :options="files" placeholder="Small" size="small" aria-label="Small" />    <TreeSelect :options="files" placeholder="Filled" variant="filled" aria-label="Filled" />    <TreeSelect :options="files" placeholder="Invalid" invalid aria-label="Invalid" />    <TreeSelect :options="files" placeholder="Disabled" disabled aria-label="Disabled" /></template>

API

Read from packages/vue/src/components/TreeSelect/types.ts, so it says what the component actually accepts.

Props

NameTypeDescription
optionsTreeNodeLike[]The tree to choose from.
selectionMode'single' | 'multiple' | 'checkbox'`'single'` (the default) closes on a choice; `'multiple'` and `'checkbox'` stay open.
placeholderstring—
display'comma' | 'chip'How the choice is shown: a comma-separated list (the default) or chips.
maxSelectedLabelsnumberPast this many, the field says how many are chosen instead of naming them.
selectedItemsLabelstringWhat it says then. `{count}`; defaults to the locale's selection message.
filterbooleanAdds a search box above the tree.
filterBystring | string[]Node fields to search, as a list or comma-separated. Defaults to `label`.
filterPlaceholderstring—
emptyMessagestring—
showClearboolean—
loadingboolean—
disabledboolean—
invalidboolean—
sizeSize—
variantInputVariant—
fluidboolean—
placementOverlayPlacement—
appendTostring`'body'` (the default), `'self'` to render in place, or a selector.

Plus pt, dt and unstyled from BaseProps, see pass-through and unstyled mode.

Emits

EventPayloadDescription
changevalue: TreeSelectValue—
node-selectnode: TreeNodeLike—
node-unselectnode: TreeNodeLike—
node-expandnode: TreeNodeLike—
node-collapsenode: TreeNodeLike—
filterquery: string—
show——
hide——
focusevent: FocusEvent—
blurevent: FocusEvent—

Slots

NameSlot propsDescription
value(props: { value: TreeNodeLike[]; placeholder?: string })The field's content.
option(props: { node: TreeNodeLike; expanded: boolean; selected: boolean; checked: boolean })A node's content in the tree.
header——
footer——
empty——
dropdownicon(props: { open: boolean })—