|$ curl https://forge-ai.dev/api/markdown?path=docs/components/tree-view
$cat docs/tree-view.md
updated Recently·28 min read·published
Tree View
Introduction
A Tree View displays hierarchical data with expandable/collapsible nodes. Common uses: file explorers, navigation menus, organizational charts, and category browsers. A well-built tree supports keyboard navigation, ARIA semantics, and efficient rendering.
Basic Tree View
TreeView.tsx
TypeScript
| 1 | "use client"; |
| 2 | import { useState } from "react"; |
| 3 | |
| 4 | interface TreeNode { |
| 5 | id: string; |
| 6 | label: string; |
| 7 | children?: TreeNode[]; |
| 8 | icon?: string; |
| 9 | } |
| 10 | |
| 11 | function TreeView({ data }: { data: TreeNode[] }) { |
| 12 | return ( |
| 13 | <div role="tree" aria-label="File explorer" className="font-mono text-sm"> |
| 14 | {data.map((node) => ( |
| 15 | <TreeNodeComponent key={node.id} node={node} depth={0} /> |
| 16 | ))} |
| 17 | </div> |
| 18 | ); |
| 19 | } |
| 20 | |
| 21 | function TreeNodeComponent({ node, depth }: { node: TreeNode; depth: number }) { |
| 22 | const [expanded, setExpanded] = useState(false); |
| 23 | const hasChildren = node.children && node.children.length > 0; |
| 24 | |
| 25 | return ( |
| 26 | <div role="treeitem" aria-expanded={hasChildren ? expanded : undefined} aria-level={depth + 1}> |
| 27 | <div |
| 28 | className="flex items-center gap-2 px-2 py-1 hover:bg-white/5 cursor-pointer" |
| 29 | style={{ paddingLeft: `${depth * 16 + 8}px` }} |
| 30 | onClick={() => hasChildren && setExpanded(!expanded)} |
| 31 | onKeyDown={(e) => { |
| 32 | if (e.key === "Enter" || e.key === " ") { |
| 33 | e.preventDefault(); |
| 34 | hasChildren && setExpanded(!expanded); |
| 35 | } |
| 36 | }} |
| 37 | tabIndex={0} |
| 38 | > |
| 39 | {hasChildren ? ( |
| 40 | <span className="text-[#525252] w-4">{expanded ? "▼" : "▶"}</span> |
| 41 | ) : ( |
| 42 | <span className="w-4" /> |
| 43 | )} |
| 44 | {node.icon && <span>{node.icon}</span>} |
| 45 | <span className="text-[#E0E0E0]">{node.label}</span> |
| 46 | </div> |
| 47 | {expanded && hasChildren && ( |
| 48 | <div role="group"> |
| 49 | {node.children!.map((child) => ( |
| 50 | <TreeNodeComponent key={child.id} node={child} depth={depth + 1} /> |
| 51 | ))} |
| 52 | </div> |
| 53 | )} |
| 54 | </div> |
| 55 | ); |
| 56 | } |
$Blueprint — Engineering Documentation·Section ID: UI-TV-01·Revision: 1.0