Props & callbacks
A complete reference for every Direactree prop, callback payload, default value, type, behavior rule, and common use case.
Props overview
| Prop | Type | Default | Purpose |
| --- | --- | --- | --- |
| structure | TreeNode[] | Required | Directory nodes rendered by the component. |
| className | string | — | Adds a class to the component root. |
| indent | number | 20 | Horizontal offset between hierarchy levels. |
| showToolbox | boolean | true | Shows create, rename, and delete controls. |
| toolboxIcons | ToolboxIcons | Built-in icons | Replaces individual toolbox icons. |
| toolboxSticky | boolean | false | Keeps the toolbox visible while its container scrolls. |
| allowDragAndDrop | boolean | true | Enables node movement. |
| isAllExpanded | boolean | false | Expands every folder for the initial render. |
| onCreateFolder | (parent: NodePath \| null) => void | — | Reports the create-folder action. |
| onCreateFile | (parent: NodePath \| null) => void | — | Reports the create-file action. |
| onRename | (node: NodePath) => void | — | Reports the rename action. |
| onDelete | (node: NodePath) => void | — | Reports the delete action. |
| onSave | (props: SaveProps) => void | — | Reports a confirmed create or rename. |
| onSelectedNodeChange | (node: NodePath \| null) => void | — | Reports selection changes. |
| onNodeMove | (node: TreeNode, target: TreeNode) => void | — | Reports a valid drag-and-drop move. |
structure
structure is the source hierarchy rendered by Direactree. Root items are array entries; nested items live in a folder's children array.
type TreeNode = {
id: string;
name: string;
type: "file" | "folder";
children?: TreeNode[];
isExpanded?: boolean;
};
Example structure:
const structure: TreeNode[] = [
{
id: "0",
name: "C:/",
type: "folder",
children: [
{
id: "1",
name: "Users",
type: "folder",
children: [
{
id: "2",
name: "John Doe",
type: "folder",
children: [
{
id: "3",
name: "Documents",
type: "folder",
children: [
{ id: "4", name: "sample.tsx", type: "file" },
],
},
{ id: "5", name: "logs.txt", type: "file" },
],
},
],
},
],
},
];
<Direactree structure={structure} />;
children is optional because files do not contain nodes and empty folders may omit it. Supplying children: [] for folders is also valid. isExpanded controls a folder's initial expansion individually; isAllExpanded can override the initial behavior for the whole tree.
Change the TreeNode array and see the rendered hierarchy update.
[
{
"id": "0",
"name": "Desktop",
"type": "folder",
"children": [
{
"id": "1",
"name": "Projects",
"type": "folder",
"children": [
{
"id": "1.1",
"name": "Web Applications",
"type": "folder",
"children": [
{
"id": "sample.txt",
"name": "project-notes.txt",
"type": "file"
},
{
"id": "example.json",
"name": "config.json",
"type": "file"
},
{
"id": "sample.ts",
"name": "utils.ts",
"type": "file"
}
]
}
]
},
{
"id": "2",
"name": "Documents",
"type": "folder",
"children": [
{
"id": "REST-API.md",
"name": "REST-API.md",
"type": "file"
}
]
},
{
"id": "DireactreeUsage.tsx",
"name": "DireactreeUsage.tsx",
"type": "file"
}
]
}
]- Desktop
Display and interaction
indent
Controls the horizontal indentation between tree levels. The accepted range is 8–50:
- Values below
8are normalized to8. - Values above
50are normalized to50.
<Direactree structure={structure} indent={28} />
Use a smaller value in narrow sidebars and a larger value when hierarchy depth should be visually prominent.
Move the slider to compare compact and spacious hierarchy levels.
- Desktop
isAllExpanded
Determines whether all folders are expanded on the initial render.
<Direactree structure={structure} isAllExpanded />
This is useful for small trees where users should see the complete hierarchy immediately. For large structures, keep the default to avoid overwhelming the interface.
The tree remounts when the value changes because this prop controls the initial render.
- Desktop
allowDragAndDrop
Enables or disables moving files and folders by dragging.
<Direactree structure={structure} allowDragAndDrop={false} />
Set it to false for read-only explorers or when your backend does not support re-parenting. This setting does not hide the toolbox; use showToolbox separately.
Toggle movement, then drag a node onto a folder.
- Desktop
null
showToolbox
Controls the built-in create-folder, create-file, rename, and delete actions.
<Direactree structure={structure} showToolbox={false} />
Disable it when the tree is only used for navigation or selection. To make a tree completely read-only, combine showToolbox={false} and allowDragAndDrop={false}.
Hide or reveal the built-in create, rename, and delete controls.
- Desktop
toolboxSticky
Keeps the toolbox visible while the tree's scroll container moves.
<div style={{ height: 320, overflow: "auto" }}>
<Direactree
structure={structure}
toolboxSticky
isAllExpanded
/>
</div>
Use it for tall trees inside a height-constrained panel. It has no visible effect when the surrounding content does not scroll.
Scroll inside the constrained area and compare the toolbox position.
- Desktop
toolboxIcons
Replaces any built-in toolbox icon with a ReactNode. Every field is optional, so icons can be changed individually.
type ToolboxIcons = {
createFolder?: React.ReactNode;
createFile?: React.ReactNode;
rename?: React.ReactNode;
delete?: React.ReactNode;
};
const toolboxIcons = {
createFolder: <FolderPlusIcon />,
createFile: <FilePlusIcon />,
rename: <EditIcon />,
delete: <TrashIcon />,
};
<Direactree
structure={structure}
toolboxIcons={toolboxIcons}
/>;
Use custom icons to match an existing design system. Icon nodes should have an accessible name when their visual meaning is not accompanied by text.
Switch between Direactree defaults and custom React nodes.
- Desktop
className
Adds a custom class name to the Direactree root element for layout-level customization.
<Direactree structure={structure} className="project-explorer" />
Prefer the component's public props for behavior and use className for spacing, sizing, and placement in your own layout.
Apply a presentation class without changing Direactree behavior.
- Desktop
Event callbacks
Callback props make it possible to observe interaction and synchronize Direactree with application state or a backend.
NodePath is used by selection and toolbox callbacks:
type NodePath = {
name: string;
id: string;
type: "file" | "folder";
parent: NodePath | null;
};
Unlike TreeNode, NodePath describes ancestry through its recursive parent field. The root node has parent: null.
onSelectedNodeChange
Called when a user selects a node or when selection becomes empty. The callback receives the selected path or null.
const [selectedNode, setSelectedNode] = useState<NodePath | null>(null);
<Direactree
structure={structure}
onSelectedNodeChange={setSelectedNode}
/>;
Use this callback to show a file preview, populate a detail panel, or enable actions for the current node.
Select a file or folder to inspect the complete NodePath.
- Desktop
null
onNodeMove
Called after a user moves a node onto a valid target folder. The first argument is the moved node and the second is its destination.
const [lastMove, setLastMove] = useState<{
source: TreeNode;
target: TreeNode;
} | null>(null);
function handleNodeMove(source: TreeNode, target: TreeNode) {
setLastMove({ source, target });
}
<Direactree structure={structure} onNodeMove={handleNodeMove} />;
The callback is not called when:
- The source is dropped onto itself.
- A folder is dropped into one of its own descendants.
- The destination is a file.
Set allowDragAndDrop={false} when moves should not be available at all.
Drag a node onto a valid folder to inspect source and target payloads.
- Desktop
null
null
Toolbox action callbacks
onCreateFolder?: (parentNode: NodePath | null) => void;
onCreateFile?: (parentNode: NodePath | null) => void;
onRename?: (node: NodePath) => void;
onDelete?: (node: NodePath) => void;
onCreateFolderfires when folder creation starts and receives the selected parent folder.onCreateFilefires when file creation starts and receives the selected parent folder.onRenamereceives the node whose name is about to be edited.onDeletereceives the node requested for deletion.
If no node is selected, the create callbacks receive null. Use this signal to create the new file or folder at the root.
function handleCreateFolder(parent: NodePath | null) {
console.log("Create folder under", parent?.id ?? "root");
}
function handleCreateFile(parent: NodePath | null) {
console.log("Create file under", parent?.id ?? "root");
}
function handleRename(node: NodePath) {
console.log("Rename", node.id);
}
function handleDelete(node: NodePath) {
console.log("Delete", node.id);
}
<Direactree
structure={structure}
onCreateFolder={handleCreateFolder}
onCreateFile={handleCreateFile}
onRename={handleRename}
onDelete={handleDelete}
/>;
Select a node and use a toolbox icon to inspect the action and NodePath.
- Desktop
null
onSave
Called when the user confirms the name in the editable area. It represents the completed create or rename input, not merely the initial toolbox click.
type SaveProps = {
newName: string;
selectedNode: NodePath | null;
actionType: "create" | "edit";
createType?: "folder" | "file";
};
Payload meaning:
| Field | Meaning |
| --- | --- |
| newName | The value confirmed by the user. |
| selectedNode | The creation parent or node being renamed. |
| actionType | create for a new node, edit for a rename. |
| createType | folder or file during creation; omitted for editing. |
const [lastSave, setLastSave] = useState<SaveProps | null>(null);
function handleSave(saveProps: SaveProps) {
setLastSave(saveProps);
// Persist to your API or update the TreeNode[] here.
}
<Direactree structure={structure} onSave={handleSave} />;
Start a create or rename action, enter a name, and confirm it.
- Desktop
null
Complete types
These are the public shapes used by the component:
interface TreeNode {
id: string;
name: string;
type: "file" | "folder";
children?: TreeNode[];
isExpanded?: boolean;
}
type NodePath = {
name: string;
id: string;
type: "file" | "folder";
parent: NodePath | null;
};
interface SaveProps {
newName: string;
selectedNode: NodePath | null;
actionType: "create" | "edit";
createType?: "folder" | "file";
}
interface ToolboxIcons {
createFolder?: React.ReactNode;
createFile?: React.ReactNode;
rename?: React.ReactNode;
delete?: React.ReactNode;
}
Import them directly from the package:
import type {
DireactreeProps,
NodePath,
SaveProps,
ToolboxIcons,
TreeNode,
} from "direactree";