Shadcn Treeview
Examples

Multi-Select

Tree view with multi-selection support

This example demonstrates multi-selection with CTRL+click.

Selected items:

None

Code

import * as React from "react";
import { TreeView, TreeViewItem, flattenTree, type ITreeViewOnSelectProps } from "shadcn-treeview";
import { FileIcon, FolderIcon, FolderOpenIcon } from "lucide-react";

export function MultiSelectTreeView() {
  const data = React.useMemo(
    () =>
      flattenTree({
        id: "root",
        name: "Root",
        children: [
          { id: "1", name: "Item 1" },
          {
            id: "2",
            name: "Item 2",
            children: [
              { id: "21", name: "Subitem 1" },
              { id: "22", name: "Subitem 2" }
            ]
          },
          { id: "3", name: "Item 3" }
        ]
      }),
    []
  );

  const [selectedNodes, setSelectedNodes] = React.useState<string[]>([]);

  const handleSelect = (props: ITreeViewOnSelectProps) => {
    setSelectedNodes((prev) =>
      props.isSelected
        ? [...prev, props.element.id.toString()]
        : prev.filter((id) => id !== props.element.id.toString())
    );
  };

  return (
    <div className="space-y-4">
      <TreeView
        data={data}
        aria-label="Multi-select tree"
        className="w-64 rounded border p-2"
        multiSelect
        togglableSelect
        onSelect={handleSelect}
        nodeRenderer={({
          element,
          isBranch,
          isExpanded,
          isSelected,
          getNodeProps,
          level
        }) => (
          <TreeViewItem
            {...getNodeProps()}
            name={element.name}
            isBranch={isBranch}
            isExpanded={isExpanded}
            isSelected={isSelected}
            level={level}
            indentation={16}
            icon={
              isBranch ? (
                isExpanded ? (
                  <FolderOpenIcon className="h-4 w-4 shrink-0 text-muted-foreground" />
                ) : (
                  <FolderIcon className="h-4 w-4 shrink-0 text-muted-foreground" />
                )
              ) : (
                <FileIcon className="h-4 w-4 shrink-0 text-muted-foreground" />
              )
            }
          />
        )}
      />

      <div className="text-sm">
        <p className="font-medium">Selected items:</p>
        <p className="text-muted-foreground">
          {selectedNodes.length > 0
            ? data
                .filter((node) => selectedNodes.includes(node.id.toString()))
                .map((node) => node.name)
                .join(", ")
            : "None"}
        </p>
      </div>
    </div>
  );
}

Selection Modes

Exclusive Select (Default)

Click selects only that item, clearing previous selection:

<TreeView clickAction="EXCLUSIVE_SELECT" />

Additive Select

Click adds to selection (CTRL+click behavior by default):

<TreeView multiSelect togglableSelect />

Propagate Selection

Select children when parent is selected:

<TreeView propagateSelect propagateSelectUpwards />

On this page