Tree
DisplayMITRecursive expandable tree view with selection, drag-reorder, and virtualization for 1000+ nodes.
bun add @otfdashkit/ui
Preview
TreeDisplay
Loading Storybook preview…
Code
@otfdashkit/uiimport { useMemo, useState } from 'react'
import { File, FolderClosed, FolderOpen } from 'lucide-react'
import { Tree, type TreeNode } from '@otfdashkit/ui'
function withFolderIcons(nodes: TreeNode[], expanded: Set<string>): TreeNode[] {
return nodes.map((n) => {
const isFolder = !!n.children
const icon = isFolder
? expanded.has(n.id)
? <FolderOpen className="h-3.5 w-3.5" strokeWidth={1.75} />
: <FolderClosed className="h-3.5 w-3.5" strokeWidth={1.75} />
: <File className="h-3.5 w-3.5" strokeWidth={1.75} />
return {
...n,
icon,
children: n.children ? withFolderIcons(n.children, expanded) : undefined,
}
})
}
const fileExplorerData: TreeNode[] = [
{
id: 'src',
label: 'src',
children: [
{
id: 'src/components',
label: 'components',
children: [
{ id: 'src/components/Button.tsx', label: 'Button.tsx' },
{ id: 'src/components/Card.tsx', label: 'Card.tsx' },
{ id: 'src/components/Modal.tsx', label: 'Modal.tsx' },
],
},
{
id: 'src/hooks',
label: 'hooks',
children: [
{ id: 'src/hooks/useDebounce.ts', label: 'useDebounce.ts' },
{ id: 'src/hooks/useMedia.ts', label: 'useMedia.ts' },
],
},
{ id: 'src/index.ts', label: 'index.ts' },
{ id: 'src/app.tsx', label: 'app.tsx' },
],
},
{
id: 'public',
label: 'public',
children: [
{ id: 'public/favicon.svg', label: 'favicon.svg' },
{ id: 'public/logo.png', label: 'logo.png' },
],
},
{ id: 'package.json', label: 'package.json' },
{ id: 'README.md', label: 'README.md' },
{ id: 'tsconfig.json', label: 'tsconfig.json' },
]
export function Example() {
const [expanded, setExpanded] = useState<string[]>(['src', 'src/components'])
const data = useMemo(
() => withFolderIcons(fileExplorerData, new Set(expanded)),
[expanded]
)
return (
<div className="max-w-sm rounded-lg border border-border bg-card p-2">
<Tree
data={data}
expandedIds={expanded}
onExpandedChange={setExpanded}
/>
</div>
)
}
Free with the SDK. This component ships in @otfdashkit/ui under the MIT license.
Props
Props declared in the Tree source. Inherited HTML attributes are not listed.
| Prop | Type | Default | Description |
|---|---|---|---|
| datarequired | TreeNode[] | ||
| defaultExpandedIds | string[] | ||
| estimatedRowHeight | number | 32 | Used when virtualize=true. Default 32. |
| expandedIds | string[] | Controlled expanded ids. | |
| onExpandedChange | (ids: string[]) => void | ||
| onMove | (sourceId: string, targetId: string, position: TreeMovePosition) => void | Define to enable drag-reorder. Omit to disable drag entirely. | |
| onSelect | (node: TreeNode) => void | ||
| selectedId | string | ||
| showLines | boolean | true | Show vertical guide lines from caret to children. Default true. |
| virtualize | boolean | false | Use @tanstack/react-virtual to virtualize visible rows. Default false. |