This document outlines the steps to create TreeView
component styled withTailwind CSS and using some npm dependency libraries.
Node.js
and npm
installed on your machine.Tailwind CSS
installed in your project.CVA(class-variance-authority)
is a utility for managing CSS class names based on various conditions.clsx
is a tiny utility for constructing className strings conditionally.1// tree-node.tsx
2import clsx from "clsx";
3import { FileIcon, FolderIcon } from "lucide-react";
4import { useState } from "react";
5import { TreeView } from ".";
6
7export interface TreeInfo {
8 key: string;
9 label: string;
10 iconType?: string;
11 childNodes?: TreeInfo[];
12}
13
14export interface Icons {
15 [key: string]: React.ReactNode;
16}
17
18interface Props {
19 node: TreeInfo;
20 icons?: Icons;
21 expandAll?: boolean;
22 showIcon?: boolean;
23 showVerticalLine?: boolean;
24}
25
26const TreeNode: React.FC<Props> = ({
27 node,
28 icons,
29 expandAll,
30 showIcon,
31 showVerticalLine,
32}) => {
33 const [showChildren, setShowChildren] = useState<boolean>(expandAll || false);
34
35 const handleClick = () => {
36 setShowChildren(!showChildren);
37 };
38
39 return (
40 <>
41 <div className="mb-2.5 flex items-center">
42 {showIcon && (
43 <div className="w-8 text-neutral-500">
44 {icons?.[node.iconType as string] ||
45 (node.childNodes === undefined ? (
46 <FileIcon width={16} height={16} />
47 ) : (
48 <FolderIcon width={16} height={16} />
49 ))}
50 </div>
51 )}
52 <span className="cursor-pointer select-none" onClick={handleClick}>
53 {node.label}
54 </span>
55 </div>
56 <ul
57 className={clsx("pl-2.5", {
58 "border-l border-neutral-200 dark:border-neutral-600": showVerticalLine,
59 })}
60 >
61 {showChildren && node.childNodes && (
62 <TreeView
63 data={node.childNodes}
64 icons={icons}
65 expandAll={expandAll}
66 showIcon={showIcon}
67 showVerticalLine={showVerticalLine}
68 />
69 )}
70 </ul>
71 </>
72 );
73};
74
75export default TreeNode;
76
1// tree-view.component.tsx
2import TreeNode, { Icons, TreeInfo } from "./tree-node";
3
4export interface TreeViewProps {
5 data: TreeInfo[];
6 icons?: Icons;
7 expandAll?: boolean;
8 showIcon?: boolean;
9 showVerticalLine?: boolean;
10 className?: string;
11}
12
13const TreeView: React.FC<TreeViewProps> = ({
14 data,
15 icons,
16 expandAll = false,
17 showIcon = true,
18 showVerticalLine = true,
19 className,
20}) => {
21 return (
22 <ul className={className}>
23 {data.map((node) => (
24 <TreeNode
25 key={node.key}
26 node={node}
27 icons={icons}
28 expandAll={expandAll}
29 showIcon={showIcon}
30 showVerticalLine={showVerticalLine}
31 />
32 ))}
33 </ul>
34 );
35};
36
37export default TreeView;
38