Tree
Data DisplayHierarchical tree view with expand and collapse.
Preview
Usage
example.jsx
import { Tree } from "@/components/ui/tree";
export default function Example() {
return <Tree />;
}Source Code
Copy this file into components/ui/tree.jsx in your project.
tree.jsx
"use client";
import { forwardRef, useState } from "react";
import { cn } from "@/lib/utils";
const TreeItem = ({ item, level = 0, defaultOpen = false }) => {
const [open, setOpen] = useState(defaultOpen);
const hasChildren = item.children && item.children.length > 0;
return (
<div>
<button
onClick={() => hasChildren && setOpen(!open)}
className={cn("flex w-full items-center gap-1 rounded-sm px-2 py-1 text-sm transition-colors hover:bg-accent",
!hasChildren && "cursor-default"
)}
style={{ paddingLeft: `${level * 16 + 8}px` }}
>
{hasChildren ? (
<svg className={cn("h-4 w-4 shrink-0 transition-transform", open && "rotate-90")} fill="none" stroke="currentColor" viewBox="0 0 24 24"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5l7 7-7 7" /></svg>
) : (
<span className="h-4 w-4" />
)}
<span className={cn(item.icon && "flex items-center gap-2")}>
{item.icon && <span>{item.icon}</span>}
{item.label}
</span>
</button>
{open && hasChildren && (
<div>{item.children.map((child, i) => <TreeItem key={i} item={child} level={level + 1} />)}</div>
)}
</div>
);
};
const Tree = forwardRef(({ className, items = [], ...props }, ref) => (
<div ref={ref} className={cn("rounded-md border p-2", className)} {...props}>
{items.map((item, i) => <TreeItem key={i} item={item} />)}
</div>
));
Tree.displayName = "Tree";
export { Tree };
Quick Install
Make sure you have the cn() utility set up. It requires clsx and tailwind-merge.
npm install clsx tailwind-merge