@usevyre/react@usevyre/vue

Tree

A hierarchical tree view for file explorers and nested navigation. Data-driven and controlled: pass a nested data array and the Tree renders recursively. A node with children is a folder; a leaf fires onSelect. Full keyboard support (/ move, /expand/collapse, Enter select).


File explorer

Click a folder to expand/collapse, a file to select. State is fully controlled — selectedId/onSelect andexpandedIds (here seeded withdefaultExpandedIds). README.md is disabled.

  • src
    • index.ts
    • components
      • Button.tsx
      • Tree.tsx
    • utils.ts
  • package.json
  • README.md

Selected: src/components/Tree.tsx

import { useState } from "react";
import { Tree } from "@usevyre/react";

const data = [
  { id: "src", label: "src", children: [
    { id: "src/index.ts", label: "index.ts" },
    { id: "src/components", label: "components", children: [
      { id: "src/components/Button.tsx", label: "Button.tsx" },
      { id: "src/components/Tree.tsx", label: "Tree.tsx" },
    ]},
    { id: "src/utils.ts", label: "utils.ts" },
  ]},
  { id: "package.json", label: "package.json" },
  { id: "README.md", label: "README.md", disabled: true },
];

const [selected, setSelected] = useState<string | null>(
  "src/components/Tree.tsx"
);

<Tree
  data={data}
  selectedId={selected}
  onSelect={setSelected}
  defaultExpandedIds={["src", "src/components"]}
/>

Props

Props

PropTypeDefaultDescription
dataTreeNode[]Nested { id, label, icon?, disabled?, children? }.
expandedIdsstring[]Controlled expanded node ids. Omit for uncontrolled.
defaultExpandedIdsstring[][]Initially expanded ids when uncontrolled.
onExpandedChange(ids: string[]) => voidFires when a folder is expanded/collapsed.
selectedIdstring | nullControlled selected node id.
defaultSelectedIdstring | nullnullInitial selection when uncontrolled.
onSelect(id: string) => voidFires with the node id (not an event).
Data-driven, not composed. Tree takes a nested array, not nested children — so AI cannot mis-nest markup, and expansion/selection stay controlled state instead of leaking into the DOM.