---
title: Tree
description: Trees display hierarchical data (file systems, org charts, or nested categories) with expand/collapse per branch.
category: Data display
---
import { meta as TreeMeta, Default } from '@/content/stories/tree';
import Canvas from '@/components/component-docs/canvas';
import Demo from '@/components/component-docs/demo';
export const config = {
dependencies: {
components: [Canvas, Demo],
scripts: [
'../../components/component-docs/demo.script.tsx',
'../../components/component-docs/canvas.script.tsx',
'../../components/component-docs/controls.script.tsx',
],
},
};
# Tree
Trees display hierarchical data (file systems, org charts, or nested categories) with expand/collapse per branch.
## Try it
## Usage
Pass a `nodes` tree structure or compose tree items as children. Bind `value` to the selected node id.
```tsx
import { RuiTree, type RuiTreeNode } from '@ecopages/radiant-ui/tree';
const nodes: RuiTreeNode[] = [
{ id: 'src', label: 'src', children: [{ id: 'app', label: 'app.ts' }] },
];
```
## Custom markup
`` coordinates any light-DOM tree that matches its query contract. The `RuiTree` helper stamps these targets; it is not required.
```tsx
import '@ecopages/radiant-ui/tree';
;
```
## Node selection
Bind `value` to highlight the active node. Use keyboard arrows to navigate and expand branches.
## Theming
Tree maps to **semantic surface and status roles**, never Tailwind palette steps:
| Part | CSS roles |
| --- | --- |
| Surface (`rui-tree`) | `background`, `on-background`, `border`, `radius-container`, `shadow-sm` |
| Branch guides | `border` |
| Node hover | `surface` |
| Selected node | `primary-container`, `on-primary-container` |
| Node focus | `surface`, `focus-ring` |
Override at the theme layer, not in component CSS.
## API
`RuiTree` is a custom element (``) that owns selection, expansion, and roving-tabindex navigation; the `RuiTree` JSX view authors tree items from a `nodes` structure.
### Attributes
| Attribute | Type | Default | Description |
| --- | --- | --- | --- |
| `label` | `string` | `''` | Accessible name for the tree. |
| `value` | `string` | `''` | Selected item's `data-value` / id. |
### Light-DOM contract
| Target | Required | Host writes | Author owns |
| --- | --- | --- | --- |
| `[role="tree"]` | yes | — | root list; view sets `aria-label`, `aria-multiselectable` |
| `[role="treeitem"]` | yes | `aria-selected`, roving `tabIndex` | `data-value`, `aria-expanded` (branch nodes) |
| `data-value` | per item | — | selection identity; fallback `id` or text |
| `[role="group"]` | for branches | `hidden` | sibling after expandable treeitem |
Do not set `aria-selected` or `tabIndex` on treeitems. Nested hosts: none.
### Events
| Event | Detail | Description |
| --- | --- | --- |
| `rui-change` | `{ value: string }` | Emitted when a tree item is selected. |
### Props
| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `nodes` | `RuiTreeNode[]` | | Tree structure for the `RuiTree` view. |
`RuiTreeNode` is `{ id, label, children?, expanded? }`.
### View helpers
| Component | Target stamped | Notes |
| --- | --- | --- |
| `RuiTree` | `[role="tree"]` with `data-ref="root"` | Accepts `nodes` or `children`. |
### CSS classes
Public BEM classes (documented via `@cssclass`):
| Class | Description |
| --- | --- |
| `.rui-tree` | Root list (`role="tree"`). |
| `.rui-tree__item` | List item wrapping a node. |
| `.rui-tree__node` | Node button (`role="treeitem"`). |
### Theme roles
| Part | CSS variables consumed |
| --- | --- |
| Surface | `--background`, `--on-background`, `--border`, `--radius-container`, `--shadow-control` |
| Branch guides | `--border` |
| Node hover | `--surface` |
| Selected node | `--primary-container`, `--on-primary-container` |
| Node focus | `--surface`, `--focus-ring` |
## Accessibility
- Tree exposes `role="tree"` with `role="treeitem"` children.
- Expand/collapse state is communicated with `aria-expanded`.
- Provide `label` so users know what hierarchy the tree represents.