/// Inputs
TreeSelect
Select-style field whose overlay is an expandable, selectable tree — single or multiple selection returning node id(s).
import { TreeSelect } from "@protocore/pds";Basics
The trigger shows the selected node's label; opening it reveals a TreeView you can expand and pick from. In single mode a pick closes the overlay. The value is the node id; controllable via value / defaultValue / onValueChange.
Multiple selection
Set selectionMode="multiple" to accumulate a string[] of ids — the overlay stays open as you toggle nodes, and the trigger lists every chosen label.
When to use it
Use TreeSelect to choose from a hierarchy that is browsed as a whole — a folder, a department, a category tree — where expanding several branches at once helps. When the choice is a strict drill-down path, Cascader's columns fit better; for a flat list use Select or MultiSelect.
Usage
Do
- Give the trigger an accessible name via a `Field` label or `aria-label`.
- Provide `defaultExpanded` so the likely branch opens on first use.
- Give each node a `textValue` when its `label` isn't plain text.
- Read node id(s) from `onValueChange` — a string in single mode, a `string[]` in multiple.
Don't
- Don't use it for a strict path down one branch — Cascader's columns are clearer.
- Don't leave the trigger unlabelled when no visible field label wraps it.
- Don't collapse everything by default when the useful nodes are buried deep.
- Don't duplicate node ids — they key both selection and expansion.
Accessibility
| Keys | Action |
|---|---|
| Enter / Space | Open the overlay, or select the focused node. |
| Arrow Up / Down | Move between visible nodes in the tree. |
| Arrow Right / Left | Expand / collapse the focused branch. |
| Esc | Close the overlay without changing the selection. |
- The overlay is a Radix Popover; the tree is the shared `TreeView`, which implements the full ARIA tree keyboard model (arrows, Home/End, type-ahead, `*`).
- The tree is a `role="tree"` of `role="treeitem"` nodes with `aria-expanded`, `aria-selected`, and `aria-level`; multiple mode adds `aria-multiselectable`.
- `invalid` sets `aria-invalid` on the trigger; the trigger exposes `aria-expanded` for its open state.
TreeSelect props
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | — | |
defaultExpanded | string[] | — | Initial expanded ids in uncontrolled mode. |
defaultOpen | boolean | — | Initial open state in uncontrolled mode. |
defaultValue | string | string[] | — | Initial selection in uncontrolled mode. |
disabled | boolean | — | Disable the whole control. |
expanded | string[] | — | Controlled expanded branch ids. |
invalid | boolean | — | Mark the field invalid — danger border plus `aria-invalid`. |
items * | TreeNode[] | — | The node forest rendered in the overlay tree. |
onExpandedChange | ((expanded: string[]) => void) | — | Fires with the next expanded-id array. |
onOpenChange | ((open: boolean) => void) | — | Fires when the overlay opens or closes. |
onValueChange | ((value: string | string[]) => void) | — | Fires with the next selection, matching `selectionMode`. |
open | boolean | — | Controlled open state of the overlay. |
placeholder | string | Select | Text shown when nothing is selected. |
selectionMode | enum | single | `single` selects one id; `multiple` toggles a set. |
separator | string | , | Separator between labels in the trigger (multiple mode). |
size | enum | md | Field height: `sm` (32) · `md` (36, default) · `lg` (40). |
style | CSSProperties | — | |
value | string | string[] | — | Controlled selection — a string (single) or string[] (multiple). |