HextaUI

Tree: Multiple selection

selectionMode="multiple" works like a file manager: click to select one row, Cmd/Ctrl+click to add or remove one, Shift+click to select a range. On touch screens a tap adds or removes the row.

Photos
beach.jpg
city.jpg
forest.jpg
mountains.jpg
Documents
invoice.pdf
notes.md
resume.pdf

1 selected

"use client"

import * as React from "react"
import { IconFile, IconFolder, IconFolderOpen } from "@tabler/icons-react"

import { Tree, TreeGroup, TreeItem, TreeItemLabel } from "@/components/ui/tree"

const photos = ["beach.jpg", "city.jpg", "forest.jpg", "mountains.jpg"]
const documents = ["invoice.pdf", "notes.md", "resume.pdf"]

export function TreeMultiple() {
  const [selected, setSelected] = React.useState<string[]>(["city.jpg"])

  return (
    <div className="flex w-full max-w-xs flex-col gap-3">
      <Tree
        aria-label="Library"
        selectionMode="multiple"
        selectedValues={selected}
        onSelectedValuesChange={setSelected}
        defaultExpandedValues={["photos", "documents"]}
      >
        <TreeItem value="photos">
          <TreeItemLabel
            icon={<IconFolder />}
            expandedIcon={<IconFolderOpen />}
          >
            Photos
          </TreeItemLabel>
          <TreeGroup>
            {photos.map((name) => (
              <TreeItem key={name} value={name}>
                <TreeItemLabel icon={<IconFile />}>{name}</TreeItemLabel>
              </TreeItem>
            ))}
          </TreeGroup>
        </TreeItem>
        <TreeItem value="documents">
          <TreeItemLabel
            icon={<IconFolder />}
            expandedIcon={<IconFolderOpen />}
          >
            Documents
          </TreeItemLabel>
          <TreeGroup>
            {documents.map((name) => (
              <TreeItem key={name} value={name}>
                <TreeItemLabel icon={<IconFile />}>{name}</TreeItemLabel>
              </TreeItem>
            ))}
          </TreeGroup>
        </TreeItem>
      </Tree>
      <p className="text-sm text-muted-foreground" aria-live="polite">
        {selected.length === 0
          ? "Nothing selected"
          : `${selected.length} selected`}
      </p>
    </div>
  )
}

This adds the example as components/examples/tree/multiple.tsx, together with the Tree component and the HextaUI theme tokens it needs.

pnpm dlx shadcn@latest add https://hextaui.com/r/tree-multiple.json

To add only the component, follow the Tree installation.

Props in this example

The Tree props this example sets, from the API reference.

PropTypeDefault
selectionMode
"none" | "single" | "multiple""single"
selectedValues
string[]–
onSelectedValuesChange
(values: string[]) => void–
defaultExpandedValues
string[]–
PropTypeDefault
valueRequired. Unique within the tree.
string–
PropTypeDefault
iconShown before the label.
ReactNode–
expandedIconCrossfades in for icon while the branch is open.
ReactNode–

Every prop is in the Tree API reference.

See them all, with keyboard support and accessibility notes, on the Tree page.