Clidey UXDocs

Tree

Tree renders a hierarchical data structure with expand/collapse, keyboard navigation, and type-ahead search. Common use cases include file explorers, category trees, and nested menu structures. Selected items are indicated with a semibold label and accent background. Focused items show a ring indicator.

Interactive example#

Tree · Live example

Selected: tokens.css

Expand folders, choose a file, or collapse the whole tree.

The code uses shared demo presentation helpers. Their complete source and styling are included in the LLM build context.

Import#

TSX

import { Tree } from '@clidey/ux';
import type { TreeDataItem } from '@clidey/ux';

Basic tree#

TSX

const treeData: TreeDataItem[] = [
  {
    id: '1',
    name: 'src',
    children: [
      {
        id: '1-1',
        name: 'components',
        children: [
          { id: '1-1-1', name: 'Button.tsx' },
          { id: '1-1-2', name: 'Card.tsx' },
          { id: '1-1-3', name: 'Input.tsx' },
        ],
      },
      {
        id: '1-2',
        name: 'lib',
        children: [
          { id: '1-2-1', name: 'utils.ts' },
          { id: '1-2-2', name: 'api.ts' },
        ],
      },
    ],
  },
  { id: '2', name: 'package.json' },
  { id: '3', name: 'tsconfig.json' },
];

<Tree data={treeData} />

With selection#

TSX

function FileExplorer() {
  const [selected, setSelected] = useState<TreeDataItem | undefined>();

  return (
    <div className="flex gap-4">
      <div className="w-56 border rounded-lg p-2">
        <Tree
          data={treeData}
          onSelectChange={setSelected}
        />
      </div>
      <div className="flex-1 p-4">
        {selected ? (
          <p>Selected: <code>{selected.name}</code></p>
        ) : (
          <p className="text-muted-foreground">Select a file</p>
        )}
      </div>
    </div>
  );
}

With default selection#

TSX

<Tree
  data={treeData}
  initialSelectedItemId="1-1-1"
  onSelectChange={(item) => console.log(item)}
/>

Expand all by default#

TSX

<Tree data={treeData} expandAll />

Custom icons#

Override the default folder and item icons:

TSX

import { IconFolder as Folder, IconFileText as FileText } from '@clidey/ux';

<Tree
  data={treeData}
  folderIcon={Folder}
  itemIcon={FileText}
/>

With per-item icons#

Set an icon on individual TreeDataItem entries:

TSX

import { IconFileCode as FileJson, IconFileCode as FileCode, IconFolder as FolderOpen } from '@clidey/ux';

const treeData: TreeDataItem[] = [
  {
    id: '1',
    name: 'src',
    icon: FolderOpen,
    children: [
      { id: '1-1', name: 'index.ts', icon: FileCode },
      { id: '1-2', name: 'config.json', icon: FileJson },
    ],
  },
];

Keyboard navigation#

Click inside the tree to focus it, then use keyboard shortcuts:

KeyAction
↑ / ↓Move focus between visible nodes
→Expand collapsed folder, or move to first child
←Collapse expanded folder, or move to parent
Enter / SpaceSelect the focused node
Home / EndJump to first / last visible node
Type a letterJump to next node whose name starts with that character

Type-ahead resets after 500ms of inactivity, allowing multi-character search (e.g., type "re" to jump to "Reports").

Controlled expand/collapse#

Control which nodes are expanded externally (useful for search filtering):

TSX

function SearchableTree() {
  const [expandedIds, setExpandedIds] = useState<string[]>([]);

  return (
    <Tree
      data={treeData}
      expandedIds={expandedIds}
      onExpandChange={setExpandedIds}
    />
  );
}

Props#

Tree

PropTypeDefaultDescription
dataTreeDataItem[] | TreeDataItem—The tree data to render.
initialSelectedItemIdstring—ID of the item selected on initial render.
onSelectChange(item: TreeDataItem | undefined) => void—Called when the selected item changes.
expandAllbooleanfalseExpands all nodes on initial render.
expandedIdsstring[]—Controlled expanded node IDs.
onExpandChange(ids: string[]) => void—Called when expand state changes.
folderIconLucideIcon—Custom icon for folder nodes.
itemIconLucideIcon—Custom icon for leaf nodes.
classNamestring—Additional CSS classes.

TreeDataItem type

TSX

type TreeDataItem = {
  id: string;
  name: string;
  icon?: LucideIcon;
  children?: TreeDataItem[];
};

Note

Keyboard navigation follows the WAI-ARIA treeview pattern. Focus remains on the tree container; individual nodes are highlighted via aria-activedescendant.

Was this page helpful?