Tree Select
Preview: Default
Select whose options are a tree. Single selection with click, Enter or Space; arrow keys only move focus and expand folders.
Import
import { TreeSelect } from '@marbleui/ui'Props
<TreeSelect>
| Prop | Type | Default | Description |
|---|---|---|---|
| options *required | TreeOption[] | — | |
| className | string | — | |
| defaultValue | string | — | |
| label | string | — | |
| onChange | (id: string) => void | — | |
| placeholder | string | 'Select…' |
Accessibility
Keyboard interaction, focus management and ARIA semantics come from the underlying primitives: React Aria Button · React Aria Dialog · React Aria DialogTrigger. Follow the primitive's docs for the full keyboard map.
Usage notes
Select whose options form a tree, such as teams inside departments; any node, parent or leaf, can be chosen. To force a leaf choice use Cascader; for a flat list use Select.
const teams: TreeOption[] = [
{ id: 'eng', label: 'Engineering', children: [{ id: 'web', label: 'Web' }, { id: 'mobile', label: 'Mobile' }] },
]
<TreeSelect label="Team" options={teams} defaultValue="web" onChange={(id) => setTeam(id)} />
- Uncontrolled:
defaultValueandonChangeuse a nodeid, unique across the tree. The trigger shows the node’s label, not its path. - Top-level nodes start expanded, deeper ones collapsed, even if they hold the selection.
- Opening moves focus into the tree. Arrow keys move focus and expand or collapse folders without choosing; click, Enter or Space chooses a node and closes the popover.
- The trigger is named by the
labelplus the chosen node or placeholder.
Example source · show· hide
import { TreeSelect, type TreeOption } from './tree-select'
const teams: TreeOption[] = [
{ id: 'eng', label: 'Engineering', children: [{ id: 'web', label: 'Web' }, { id: 'mobile', label: 'Mobile' }, { id: 'infra', label: 'Infrastructure', children: [{ id: 'sre', label: 'SRE' }, { id: 'data', label: 'Data platform' }] }] },
{ id: 'design', label: 'Design', children: [{ id: 'product', label: 'Product design' }, { id: 'brand', label: 'Brand' }] },
{ id: 'gtm', label: 'Go-to-market', children: [{ id: 'sales', label: 'Sales' }, { id: 'marketing', label: 'Marketing' }] },
]
export const styles = { Default: () => <TreeSelect className="w-72" label="Team" options={teams} />, Preselected: () => <TreeSelect className="w-72" label="Team" options={teams} defaultValue="sre" /> }Source: packages/ui/src/tree-select/tree-select.tsx
Catalog
- Category
- selection
- Priority
- Extra
- Primitive
- composed
- React Aria
- Tree + Popover