Tree
Hierarchical navigation and checkable node lists with keyboard navigation.
Tree is a standalone component driven by typed node data.
import { KuiTree, type KuiTreeNode } from '@kikita-labs/ui';Provide stable node ids and bind selected or checked state from signals.
<div class="basic-tree-example">
<kui-tree
ariaLabel="Project files"
[data]="nodes"
[(value)]="selectedId"
[(expandedIds)]="expandedIds"
/>
</div>Use display mode for navigation and checkable mode for multi-select hierarchies.
- Checkable mode cascades checked state to non-disabled descendants.
- Partially checked parents expose mixed state when descendants differ.
- Lazy nodes call loadChildren once on first expansion and cache the result.
- Built-in icons are limited to folder and file; very large trees are not virtualized.
Set defaults.tree once for the application or for a subtree. Each option resolves as local input > defaults.tree.<option> > built-in default.
import { provideKikitaUi } from '@kikita-labs/ui';
export const appConfig: ApplicationConfig = {
providers: [
provideKikitaUi({
defaults: {
tree: {
/* options below */
},
},
}),
],
};| Name | Type | Default | Description |
|---|---|---|---|
| size | 'xs' | 'sm' | 'md' | 'lg' | — | Component size. Takes precedence over the global defaults.size. |
| mode | 'display' | 'checkable' | — | Default mode. |
| disclosureIcon | KuiIconGlyph | — | Icon of the expand control. Takes precedence over defaults.icons.disclosure. See Structural Icons. |
Set any of these on the component or an ancestor to restyle one part. Each token is optional: when it is not set, the part uses the role or scale token in the default column.
| Name | Type | Default | Description |
|---|---|---|---|
| --kui-tree-row-color | CSS custom property | --kui-color-text | Row color |
| --kui-tree-row-focus-ring-color | CSS custom property | --kui-color-focus | Row focus ring color |
| --kui-tree-spinner-track-color | CSS custom property | --kui-color-surface-sunken | Spinner track color |
| --kui-tree-spinner-color | CSS custom property | --kui-color-primary-indicator | Spinner color |
| Name | Type | Default | Description |
|---|---|---|---|
| --kui-tree-row-gap | CSS custom property | --kui-space-2 | Row gap |
| --kui-tree-row-padding-inline | CSS custom property | --kui-space-2 | Row padding, inline |
| --kui-tree-label-font-size | CSS custom property | --kui-text-sm-size | Label font size |
| --kui-tree-label-font-size-sm | CSS custom property | --kui-text-xs-size | Label font size, sm |
| --kui-tree-label-font-size-lg | CSS custom property | --kui-text-base-size | Label font size, lg |
| --kui-tree-toggle-size | CSS custom property | 20px (16px sm, 24px lg) | Toggle and spacer size |
| --kui-tree-icon-size | CSS custom property | 16px (14px sm, 18px lg) | Node icon size |
| --kui-tree-spinner-size | CSS custom property | 14px | Loading spinner size |
Every text the component owns (accessible names, visible words, announcements) is a typed message with an English default. Override it for the application with provideKikitaUi({ messages }), or for a subtree with provideKuiMessages.
| Name | Type | Default | Description |
|---|---|---|---|
| label | string | — | Accessible name of the tree when ariaLabel is not set. Default Tree. |
Inputs verified against @kikita-labs/ui v2.0.0 public typings and package docs.
| Name | Type | Default | Description |
|---|---|---|---|
| mode | 'display' | 'checkable' | undefined | undefined | Selects navigation-style rows or checkbox rows with cascade. Falls back to defaults.tree.mode, then display. |
| size | 'xs' | 'sm' | 'md' | 'lg' | undefined | undefined | Controls row height and label scale; only sm, md and lg have dedicated styling. Falls back to defaults.tree.size, then the root size, then md. |
| data | readonly KuiTreeNode[] | [] | Root nodes rendered by the tree. |
| ariaLabel | string | undefined | undefined | Accessible name for the role="tree" container. Falls back to the tree.label message (Tree). |
| mobile | boolean | false | Increases toggle hit targets to support touch layouts. |
| [(value)] | string | null | null | Controlled selected node id in display mode. |
| [(selected)] | string | null | null | Deprecated alias for value, kept in sync with it. Use value instead; planned for removal in the next major version. |
| [(checkedIds)] | string[] | [] | Controlled checked node ids in checkable mode. |
| [(expandedIds)] | string[] | [] | Controlled expanded node ids. |
| loadChildren | (node: KuiTreeNode) => Promise<readonly KuiTreeNode[]> | - | Lazy child loader called once for nodes marked lazy. |
| KuiTreeNode.icon | 'folder' | 'file' | - | Optional built-in glyph. Custom icon templates are not implemented. |
| KuiTreeOptions | interface | - | Shape of defaults.tree: size, mode and disclosureIcon. |
Tree uses ARIA tree semantics with roving tabindex keyboard navigation.
- Set ariaLabel when nearby text does not already name the tree.
- Arrow keys, Home, End, Enter, Space, and type-ahead move through visible nodes.
- Disabled nodes stay reachable by navigation but cannot be selected or checked.
- The root is
role="tree"and nodes arerole="treeitem"witharia-expanded,aria-selected(display) oraria-checked(checkable, includingmixed), andaria-level,aria-setsizeandaria-posinset. Exactly one node is in the tab order (roving tabindex). - Without
ariaLabelthe tree is named by thetree.labelmessage. - Use mobile mode where touch targets need the larger 44px toggle affordance.
Consumer-visible changes of @kikita-labs/ui 2.0 for Tree.
- The component class is
KuiTree; theComponentsuffix is gone. - Size and mode defaults moved to
provideKuiDefaults({ tree: { size, mode } }), together with thedisclosureIconglyph; the inputs are nowundefineduntil set. - The default
ariaLabelcomes from thetree.labelmessage. - Row, spinner and focus colours have tokens, plus gap, padding, font-size and icon-size geometry tokens.