0.1.0

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.

import { RuiTree, type RuiTreeNode } from '@ecopages/radiant-ui/tree';
 
const nodes: RuiTreeNode[] = [
  { id: 'src', label: 'src', children: [{ id: 'app', label: 'app.ts' }] },
];
 
<RuiTree nodes={nodes} value="app" label="Project files" />

Custom markup

<rui-tree> coordinates any light-DOM tree that matches its query contract. The RuiTree helper stamps these targets; it is not required.

import '@ecopages/radiant-ui/tree';
 
<rui-tree value="app" label="Project files">
  <ul role="tree" aria-label="Project files" aria-multiselectable="false">
    <li>
      <button type="button" role="treeitem" data-value="src" aria-expanded="true">
        src
      </button>
      <ul role="group">
        <li>
          <button type="button" role="treeitem" data-value="app">
            app.ts
          </button>
        </li>
      </ul>
    </li>
  </ul>
</rui-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:

PartCSS roles
Surface (rui-tree)background, on-background, border, radius-container, shadow-sm
Branch guidesborder
Node hoversurface
Selected nodeprimary-container, on-primary-container
Node focussurface, focus-ring

Override at the theme layer, not in component CSS.

API

RuiTree is a custom element (<rui-tree>) that owns selection, expansion, and roving-tabindex navigation; the RuiTree JSX view authors tree items from a nodes structure.

Attributes

AttributeTypeDefaultDescription
labelstring''Accessible name for the tree.
valuestring''Selected item's data-value / id.

Light-DOM contract

TargetRequiredHost writesAuthor owns
[role="tree"]yes—root list; view sets aria-label, aria-multiselectable
[role="treeitem"]yesaria-selected, roving tabIndexdata-value, aria-expanded (branch nodes)
data-valueper item—selection identity; fallback id or text
[role="group"]for brancheshiddensibling after expandable treeitem

Do not set aria-selected or tabIndex on treeitems. Nested hosts: none.

Events

EventDetailDescription
rui-change{ value: string }Emitted when a tree item is selected.

Props

PropTypeDefaultDescription
nodesRuiTreeNode[]Tree structure for the RuiTree view.

RuiTreeNode is { id, label, children?, expanded? }.

View helpers

ComponentTarget stampedNotes
RuiTree[role="tree"] with data-ref="root"Accepts nodes or children.

CSS classes

Public BEM classes (documented via @cssclass):

ClassDescription
.rui-treeRoot list (role="tree").
.rui-tree__itemList item wrapping a node.
.rui-tree__nodeNode button (role="treeitem").

Theme roles

PartCSS 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.