ComponentsPickers

Tree select

Pick from hierarchical data — product categories, departments, locations and warehouses, folder destinations, a chart of accounts. A searchable tree in a popover (or inline), single or multi with tri-state cascade, lazy branches, search that keeps ancestors, leaf-only selection and “Add category”. Built on the same useTree model as Tree view.

Radix Popover + WAI-ARIA treeview components/tree-select.tsx, components/tree-view.tsx, lib/use-tree.tstheme · material · accent · density · font

Products appear under this category in the store menu.

Installation

$ pnpm add @vamos-ui/react

The whole kit as one package — get updates by bumping the version. Add the styles to globals.css: @import "@vamos-ui/react/styles.css";

Usage

import { Field, TreeSelect, type TreeNode } from "@vamos-ui/react";

<Field label="Category">
  <TreeSelect nodes={categories} value={categoryId} onValueChange={setCategoryId} />
</Field>

Examples

Multiple with cascade

Checking a parent checks its descendants; a partly checked parent shows a dash (aria-checked="mixed"). valueMode picks what the value lists: all, the topmost checked (parent) or leaves.

Türkiye

Check a country to cover all of its cities. The value lists the topmost checked nodes.

value: ["tr"]

Lazy branches

Nodes with hasChildren load through loadChildren on first open (spinner in the row, retry on error).

Sub-teams load when a branch opens.

Inline with “Add”

mode="inline" for an editor side panel. onCreate adds under the focused node; add the returned node to nodes yourself.

API

TreeSelect

PropTypeDefault
nodes
The hierarchy: { id, label, children?, hasChildren?, disabled?, icon?, description?, keywords? }.
TreeNode[]—
multiple
Checkboxes; value becomes string[].
booleanfalse
value / defaultValue
Controlled / initial id(s).
string | null · string[]—
onValueChange
Called with the new value.
(id, node) => void · (ids) => void—
cascade
Multi: parent checks descendants (tri-state).
booleantrue
valueMode
Multi + cascade: what a fully checked branch yields.
"all" | "parent" | "leaf""all"
selectable
Can parents be chosen?
"any" | "leaf""any"
loadChildren
Lazy children for nodes with hasChildren.
(node, signal) => Promise<TreeNode[]>—
showPath
Trigger shows “Electronics › Phones” (› mirrors in RTL).
booleantrue
defaultExpanded
Initially open branches.
string[] | "selected""selected"
onCreate
Adds an “Add” footer that creates under the focused node.
(parentId, label) => TreeNode | Promise<TreeNode>—
searchable
Show the search box.
booleantrue
mode
inline renders the tree in place.
"popover" | "inline""popover"
height
Max tree height in px.
number288
size
Trigger and row size.
"sm" | "md" | "lg""md"
placeholder / searchPlaceholder
Trigger and search texts.
string—
name
Hidden input(s) for form posts.
string—
disabled / readOnly / invalid / required
Also read from the surrounding Field.
boolean—
labels
Built-in strings (namespace treeSelect).
Partial<TreeSelectLabels>—