# TreeSelect
A built-in tag for selecting one value from a hierarchy — a dropdown whose options are a
collapsible tree. Click a folder to expand it; click a leaf to select it. Set `searchable`
to filter the tree as you type. It hydrates into a fully interactive island just like the
other select tags.
Use it as `{% treeselect %}` in Markdown, or call it from Python logic
(loops, snippets) via `component('aardvark', 'treeselect', …)`.
## Basic tree select
The hierarchy comes through `data` — a JSON array of nested nodes, each an object with a
`value`, a `label`, and an optional `children` array of the same shape. Only leaf nodes
(those without `children`) resolve to a selection; clicking a branch just expands or
collapses it. `clearable` shows an × to reset:
Source: Markdown
```aardvark
{% treeselect label='Pick a file' placeholder='Browse…' clearable=true data='[
{"value":"src","label":"src","children":[
{"value":"src/app.py","label":"app.py"},
{"value":"src/utils","label":"utils","children":[
{"value":"src/utils/text.py","label":"text.py"}
]}
]},
{"value":"README.md","label":"README.md"}
]' %}
```
Source: Python
```python
component('aardvark', 'treeselect',
label='Pick a file', placeholder='Browse…', clearable=True,
data='''[
{"value":"src","label":"src","children":[
{"value":"src/app.py","label":"app.py"},
{"value":"src/utils","label":"utils","children":[
{"value":"src/utils/text.py","label":"text.py"}
]}
]},
{"value":"README.md","label":"README.md"}
]''')
```
## Sizes, variants, description, and search
`size` runs `xs`–`xl`; `variant` is `default`, `filled`, or `unstyled`. `description` adds
helper text below the label, and `error` shows a validation message. `searchable` adds a
search field that filters the tree as you type:
Source: Markdown
```aardvark
{% treeselect label='Category' description='Pick the deepest matching node' size='md' variant='filled' radius='md' searchable=true data='[
{"value":"hardware","label":"Hardware","children":[
{"value":"hardware/laptops","label":"Laptops"},
{"value":"hardware/phones","label":"Phones"}
]},
{"value":"software","label":"Software","children":[
{"value":"software/os","label":"Operating systems"}
]}
]' %}
```
Source: Python
```python
component('aardvark', 'treeselect',
label='Category', description='Pick the deepest matching node',
size='md', variant='filled', radius='md', searchable=True,
data='''[
{"value":"hardware","label":"Hardware","children":[
{"value":"hardware/laptops","label":"Laptops"},
{"value":"hardware/phones","label":"Phones"}
]},
{"value":"software","label":"Software","children":[
{"value":"software/os","label":"Operating systems"}
]}
]''')
```
## Data shape
Each node is an object:
```json
{
"value": "unique-id",
"label": "Display text",
"children": [ /* more nodes, optional */ ]
}
```
`value` must be unique across the whole tree — it's what gets selected; `label` is what the
reader sees. A node with no `children` is a selectable leaf. Unlike the flat select family,
`treeselect` takes only this nested JSON tree, not a comma-separated `data` list.
## With other components
A tree select fits inside a [card](/components/data-display/card/) alongside other content —
here a [text](/components/typography/text/) lead-in above the field:
Choose where this document lives.
Source: Markdown
```aardvark
{% card %}
{% text size='sm' c='dimmed' %}Choose where this document lives.{% endText %}
{% treeselect label='Location' placeholder='Browse…' clearable=true data='[
{"value":"docs","label":"docs","children":[
{"value":"docs/guide","label":"guide"},
{"value":"docs/reference","label":"reference"}
]},
{"value":"blog","label":"blog"}
]' %}
{% endCard %}
```
Source: Python
```python
tree = '''[
{"value":"docs","label":"docs","children":[
{"value":"docs/guide","label":"guide"},
{"value":"docs/reference","label":"reference"}
]},
{"value":"blog","label":"blog"}
]'''
component('aardvark', 'card', children=(
component('aardvark', 'text', children='Choose where this document lives.', size='sm', c='dimmed') +
component('aardvark', 'treeselect',
label='Location', placeholder='Browse…', clearable=True, data=tree)
))
```
## Attributes
Every attribute is optional; omit one to take its Mantine default. The body is ignored —
`treeselect` is a form control, not a container.
| Attribute | Valid values | Description |
| --- | --- | --- |
| `data` | JSON array string | The hierarchy — a JSON array of nested `{value, label, children}` nodes. A node without `children` is a selectable leaf. |
| `label` | String | The field label. |
| `placeholder` | String | Empty-state text on the trigger. |
| `description` | String | Helper text below the label. |
| `error` | String | Validation message; also styles the field red. |
| `size` | `xs`, `sm`, `md`, `lg`, `xl` | Input size. |
| `radius` | `xs`, `sm`, `md`, `lg`, `xl` | Corner radius. |
| `variant` | `default`, `filled`, `unstyled` | Input style. |
| `clearable` | `true`, `false` (default `false`) | Show an × to clear the selection. |
| `searchable` | `true`, `false` (default `false`) | Add a search field that filters the tree as you type. |
| `disabled` | `true`, `false` (default `false`) | Disable the input. |
## CSS Selectors
Target the rendered element through its island marker — `[data-aardvark-island="TreeSelect"]` — or through the Mantine Styles API classes (`.mantine-TreeSelect-root` and its inner parts):
```css
/* Every rendered TreeSelect carries this island marker */
[data-aardvark-island="TreeSelect"] { }
/* Mantine Styles API class on the root element */
.mantine-TreeSelect-root { }
.mantine-TreeSelect-input { }
.mantine-TreeSelect-label { }
.mantine-TreeSelect-wrapper { }
```
## Injecting Attributes
`attr={…}` forwards raw HTML attributes straight onto the rendered element. A read-only combobox manages its own click and selection (React state — there's no native `change`/`click` to hook from an inline handler), so `attr` is best here for a static `data-*` hook, an `id`, or ARIA. It lands on the rendered input, where scripts, tests, or DevTools can find it:
Source: Markdown
```aardvark
{% treeselect label='Pick a file' placeholder='Browse…' clearable=true data='[
{"value":"src","label":"src","children":[
{"value":"src/app.py","label":"app.py"}
]},
{"value":"README.md","label":"README.md"}
]' attr={'data-testid': 'file-treeselect'} %}
```
Source: Python
```python
component('aardvark', 'treeselect',
label='Pick a file', placeholder='Browse…', clearable=True,
data='''[
{"value":"src","label":"src","children":[
{"value":"src/app.py","label":"app.py"}
]},
{"value":"README.md","label":"README.md"}
]''',
attr={'data-testid': 'file-treeselect'})
```