Component
Tree
A hierarchical list of expandable nodes. Feed it a nested data model, control expansion and selection (single or multiple), add cascading checkboxes with a select-all, filter with a built-in search box, virtualise long lists, show a loading skeleton, and template the node label or toggle icon.
Nodes, expansion & selection
Birches
Birch
Alder
Oaks & beeches
autumn-notes.txt
selected: [betula] · last click: —
import { ChangeDetectionStrategy, Component, signal } from '@angular/core';
import { provideIcons } from '@ng-icons/core';
import { phosphorFile, phosphorFolder, phosphorLeaf } from '@ng-icons/phosphor-icons/regular';
import { HbTreeImports, type HbTreeKey, type HbTreeNode } from '@herbst/ui';
@Component({
selector: 'hb-demo-tree-basic',
imports: [HbTreeImports],
viewProviders: [provideIcons({ phosphorFolder, phosphorFile, phosphorLeaf })],
template: `
<div class="w-full max-w-xs">
<hb-tree
[hbNodes]="nodes"
[(hbExpanded)]="expanded"
[(hbSelection)]="selection"
hbSelectionMode="single"
hbAriaLabel="Herbst"
(hbNodeClick)="clicked.set($any($event).label)"
/>
<p class="mt-3 font-mono text-[12px] text-muted-foreground">
selected: [{{ selection().join(', ') }}] · last click: {{ clicked() }}
</p>
</div>
`,
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class HbDemoTreeBasicComponent {
protected readonly expanded = signal<HbTreeKey[]>(['betulaceae']);
protected readonly selection = signal<HbTreeKey[]>(['betula']);
protected readonly clicked = signal('—');
protected readonly nodes: HbTreeNode[] = [
{
key: 'betulaceae',
label: 'Birches',
icon: 'phosphorFolder',
children: [
{ key: 'betula', label: 'Birch', icon: 'phosphorLeaf' },
{ key: 'alnus', label: 'Alder', icon: 'phosphorLeaf' },
],
},
{
key: 'fagaceae',
label: 'Oaks & beeches',
icon: 'phosphorFolder',
children: [
{ key: 'quercus', label: 'Oak', icon: 'phosphorLeaf' },
{ key: 'fagus', label: 'Beech', icon: 'phosphorLeaf', disabled: true },
],
},
{ key: 'notes', label: 'autumn-notes.txt', icon: 'phosphorFile', leaf: true },
];
}
Cascading checkboxes
checked: [birch]
Filter & custom templates
Europe 3
Asia 2
selected: []
API reference
hb-tree — data & selection
| Property | Description | Type | Default |
|---|---|---|---|
| [hbNodes] | The tree data. Each node is { key, label, icon?, children?, leaf?, disabled?, selectable?, loading?, data? }. | HbTreeNode[] | [] |
| [(hbExpanded)] | The keys of expanded nodes, two-way bound. | HbTreeKey[] | [] |
| [hbSelectionMode] / [(hbSelection)] | Row selection mode and the selected keys (two-way). | 'none' | 'single' | 'multiple' / HbTreeKey[] | 'single' / [] |
| [hbMetaKeySelection] | Multiple mode — require Ctrl/Cmd to add to the selection instead of toggling freely. | boolean | false |
hb-tree — checkboxes & filtering
| Property | Description | Type | Default |
|---|---|---|---|
| [hbCheckable] / [(hbChecked)] | Show a checkbox per node and two-way bind the checked keys. | boolean / HbTreeKey[] | false / [] |
| [hbCheckStrictly] / [hbShowSelectAll] | Independent checkboxes (no parent/child cascade), and a select-all header with an indeterminate state. | boolean | false |
| [hbShowFilter] / [hbFilter] | Show the built-in search box, or drive filtering yourself with a controlled query string. | boolean / string | false / "" |
| [hbFilterMode] / [hbFilterPlaceholder] | Lenient keeps the matched node’s descendants visible; strict shows only matches and ancestors. Plus the search placeholder. | 'lenient' | 'strict' / string | 'lenient' / 'Filter…' |
hb-tree — rendering & events
| Property | Description | Type | Default |
|---|---|---|---|
| [hbVirtualScroll] / [hbItemSize] / [hbScrollHeight] | Virtualise the flattened list with a fixed row height and viewport height. | boolean / number / string | false / 32 / '16rem' |
| [hbLoading] / [hbSkeletonRows] | Replace the tree with skeleton rows while data loads. | boolean / number | false / 6 |
| [hbToggleIcon] / [hbIndent] / [hbAriaLabel] | The expand icon name, per-level indentation in pixels, and the tree’s accessible label. | string / number / string | 'phosphorCaretRight' / 16 / '' |
| (hbNodeExpand) / (hbNodeCollapse) / (hbNodeClick) | Emit the node when it is expanded, collapsed, or clicked. | HbTreeNode | — |
| ng-template[hbTreeNodeContent] / [hbTreeToggle] | Template the node label (ctx: $implicit = node, level) and the toggle icon (ctx: $implicit = expanded, node). | template | — |