Strongtie Design System
Getting StartedComponents

Command Palette

Search for a command to run...

Getting Started
  • Introduction
  • Setup Guide
  • Package Installation
  • Code Quality Setup
  • Migration Guide
  • Resources
Registry
  • Getting Started
  • Combobox
  • Datepicker
  • MultiSelect
  • Tree
Guides
  • Framework Recommendations
Foundations
  • States
  • Variables
Components
  • Accordion
  • Alert
  • Alert Dialog
  • Avatar
  • Badge
  • Breadcrumb
  • Button
  • Button Group
  • Calendar
  • Card
  • Carousel
  • Chart
  • Checkbox
  • Collapsible
  • Command
  • Combobox
  • Context Menu
  • Date Picker
  • Dialog
  • Drawer
  • Dropdown Menu
  • Empty
  • Field
  • Hover Card
  • Input
  • Input Group
  • Item
  • Kbd
  • Label
  • Menubar
  • Multi Select
  • Navigation Menu
  • Pagination
  • Popover
  • Progress
  • Radio Group
  • Scroll Area
  • Select
  • Separator
  • Sheet
  • Sidebar
  • Skeleton
  • Slider
  • Switch
  • Table
  • Tabs
  • Textarea
  • Toaster
  • Toggle
  • Toggle Group
  • Tooltip
  • Tree
2026 Simpson Strong-Tie
  1. Docs
  2. Registry
  3. Tree

Tree

Previous

A hierarchical list component that displays nested data in an expandable tree structure.

Tree views are used to display hierarchical data such as file systems, organizational charts, navigation menus, or any nested data structure. Users can expand and collapse parent nodes to reveal or hide their children, making it easy to navigate through complex nested information.

This is a composable component that provides full control over the tree structure. Use TreeItem, TreeItemTrigger, TreeItemIndicator, TreeItemIcon, TreeItemLabel, and TreeItemContent to build your tree.

Registry Component: This component is available from the Strongtie registry. Add it using: npx shadcn@latest add @strongtie/tree

Example

"use client"

import * as React from "react"
import {
  Tree,
  TreeItem,
  TreeItemContent,
  TreeItemIcon,
  TreeItemIndicator,
  TreeItemLabel,
  TreeItemTrigger,
} from "@/components/ui/tree"
import type { TreeItemData } from "@/components/ui/tree"

const treeData: TreeItemData[] = [
  {
    id: "1",
    name: "src",
    type: "folder",
    children: [
      {
        id: "2",
        name: "components",
        type: "folder",
        children: [
          { id: "3", name: "Button.tsx", type: "file" },
          { id: "4", name: "Input.tsx", type: "file" },
          { id: "5", name: "Card.tsx", type: "file" },
        ],
      },
      {
        id: "6",
        name: "utils",
        type: "folder",
        children: [
          { id: "7", name: "helpers.ts", type: "file" },
          { id: "8", name: "constants.ts", type: "file" },
        ],
      },
      { id: "9", name: "index.ts", type: "file" },
    ],
  },
  {
    id: "10",
    name: "public",
    type: "folder",
    children: [
      {
        id: "11",
        name: "images",
        type: "folder",
        children: [{ id: "12", name: "logo.png", type: "file" }],
      },
    ],
  },
  { id: "13", name: "package.json", type: "file" },
  { id: "14", name: "README.md", type: "file" },
]

interface TreeDataItem extends TreeItemData {
  children?: TreeDataItem[]
}

function renderTreeItems(items: TreeDataItem[]) {
  return items.map((item) => (
    <TreeItem key={item.id} id={item.id} value={item}>
      <TreeItemTrigger>
        <TreeItemIndicator />
        <TreeItemIcon />
        <TreeItemLabel>{item.name}</TreeItemLabel>
      </TreeItemTrigger>
      {item.children && (
        <TreeItemContent>{renderTreeItems(item.children)}</TreeItemContent>
      )}
    </TreeItem>
  ))
}

export function TreeDefault() {
  const [selected, setSelected] = React.useState<string>()

  return (
    <div className="w-full max-w-md rounded-md border p-4">
      <Tree
        selected={selected}
        onSelect={(id) => {
          setSelected(id)
          console.log("Selected:", id)
        }}
      >
        {renderTreeItems(treeData)}
      </Tree>
    </div>
  )
}

Installation

Add this component from the Strongtie registry:

npx shadcn@latest add @strongtie/tree

Or by URL:

npx shadcn@latest add https://design.strongtie.io/r/tree.json

Usage

import { Tree } from "@/components/ui/tree"

Props

<TreeItemContent>

PropTypeDefaultDescription
defaultExpandedstring[]-Array of item IDs that should be expanded by default
expandedstring[]-Controlled array of expanded item IDs
onExpandedChange((expanded: string[]) => void)-Callback when expanded items change
onSelect((id: string, item: TreeItemData) => void)-Callback when an item is selected
selectedstring-ID of the currently selected item

Examples

Default

"use client"

import * as React from "react"
import {
  Tree,
  TreeItem,
  TreeItemContent,
  TreeItemIcon,
  TreeItemIndicator,
  TreeItemLabel,
  TreeItemTrigger,
} from "@/components/ui/tree"
import type { TreeItemData } from "@/components/ui/tree"

const treeData: TreeItemData[] = [
  {
    id: "1",
    name: "src",
    type: "folder",
    children: [
      {
        id: "2",
        name: "components",
        type: "folder",
        children: [
          { id: "3", name: "Button.tsx", type: "file" },
          { id: "4", name: "Input.tsx", type: "file" },
          { id: "5", name: "Card.tsx", type: "file" },
        ],
      },
      {
        id: "6",
        name: "utils",
        type: "folder",
        children: [
          { id: "7", name: "helpers.ts", type: "file" },
          { id: "8", name: "constants.ts", type: "file" },
        ],
      },
      { id: "9", name: "index.ts", type: "file" },
    ],
  },
  {
    id: "10",
    name: "public",
    type: "folder",
    children: [
      {
        id: "11",
        name: "images",
        type: "folder",
        children: [{ id: "12", name: "logo.png", type: "file" }],
      },
    ],
  },
  { id: "13", name: "package.json", type: "file" },
  { id: "14", name: "README.md", type: "file" },
]

interface TreeDataItem extends TreeItemData {
  children?: TreeDataItem[]
}

function renderTreeItems(items: TreeDataItem[]) {
  return items.map((item) => (
    <TreeItem key={item.id} id={item.id} value={item}>
      <TreeItemTrigger>
        <TreeItemIndicator />
        <TreeItemIcon />
        <TreeItemLabel>{item.name}</TreeItemLabel>
      </TreeItemTrigger>
      {item.children && (
        <TreeItemContent>{renderTreeItems(item.children)}</TreeItemContent>
      )}
    </TreeItem>
  ))
}

export function TreeDefault() {
  const [selected, setSelected] = React.useState<string>()

  return (
    <div className="w-full max-w-md rounded-md border p-4">
      <Tree
        selected={selected}
        onSelect={(id) => {
          setSelected(id)
          console.log("Selected:", id)
        }}
      >
        {renderTreeItems(treeData)}
      </Tree>
    </div>
  )
}

Custom Icons

"use client"

import * as React from "react"
import {
  Tree,
  TreeItem,
  TreeItemContent,
  TreeItemIcon,
  TreeItemIndicator,
  TreeItemLabel,
  TreeItemTrigger,
} from "@/components/ui/tree"
import {
  Activity,
  Calendar,
  Cpu,
  Database,
  HardDrive,
  Hash,
  Key,
  Link,
  ListTree,
  Lock,
  Server,
  Settings,
  Shield,
  Table,
  ToggleLeft,
  Type,
  Users,
} from "lucide-react"

export function TreeCustomIcons() {
  const [selected, setSelected] = React.useState<string>()

  return (
    <div className="w-full max-w-lg rounded-md border p-4">
      <Tree
        selected={selected}
        onSelect={(id) => setSelected(id)}
        defaultExpanded={["db", "users-table", "infrastructure"]}
      >
        {/* Database Section */}
        <TreeItem id="db" value={{ id: "db", name: "Production Database" }}>
          <TreeItemTrigger>
            <TreeItemIndicator />
            <TreeItemIcon>
              <Database className="size-4 text-blue-500" />
            </TreeItemIcon>
            <TreeItemLabel>Production Database</TreeItemLabel>
          </TreeItemTrigger>
          <TreeItemContent>
            {/* Users Table */}
            <TreeItem
              id="users-table"
              value={{ id: "users-table", name: "users" }}
            >
              <TreeItemTrigger>
                <TreeItemIndicator />
                <TreeItemIcon>
                  <Table className="size-4 text-emerald-500" />
                </TreeItemIcon>
                <TreeItemLabel>users</TreeItemLabel>
              </TreeItemTrigger>
              <TreeItemContent>
                <TreeItem id="users-id" value={{ id: "users-id", name: "id" }}>
                  <TreeItemTrigger>
                    <TreeItemIndicator />
                    <TreeItemIcon>
                      <Key className="size-4 text-amber-500" />
                    </TreeItemIcon>
                    <TreeItemLabel>id (primary key)</TreeItemLabel>
                  </TreeItemTrigger>
                </TreeItem>
                <TreeItem
                  id="users-email"
                  value={{ id: "users-email", name: "email" }}
                >
                  <TreeItemTrigger>
                    <TreeItemIndicator />
                    <TreeItemIcon>
                      <Type className="size-4 text-purple-500" />
                    </TreeItemIcon>
                    <TreeItemLabel>email (varchar)</TreeItemLabel>
                  </TreeItemTrigger>
                </TreeItem>
                <TreeItem
                  id="users-created"
                  value={{ id: "users-created", name: "created_at" }}
                >
                  <TreeItemTrigger>
                    <TreeItemIndicator />
                    <TreeItemIcon>
                      <Calendar className="size-4 text-rose-500" />
                    </TreeItemIcon>
                    <TreeItemLabel>created_at (timestamp)</TreeItemLabel>
                  </TreeItemTrigger>
                </TreeItem>
                <TreeItem
                  id="users-active"
                  value={{ id: "users-active", name: "is_active" }}
                >
                  <TreeItemTrigger>
                    <TreeItemIndicator />
                    <TreeItemIcon>
                      <ToggleLeft className="size-4 text-cyan-500" />
                    </TreeItemIcon>
                    <TreeItemLabel>is_active (boolean)</TreeItemLabel>
                  </TreeItemTrigger>
                </TreeItem>
              </TreeItemContent>
            </TreeItem>

            {/* Posts Table */}
            <TreeItem
              id="posts-table"
              value={{ id: "posts-table", name: "posts" }}
            >
              <TreeItemTrigger>
                <TreeItemIndicator />
                <TreeItemIcon>
                  <Table className="size-4 text-emerald-500" />
                </TreeItemIcon>
                <TreeItemLabel>posts</TreeItemLabel>
              </TreeItemTrigger>
              <TreeItemContent>
                <TreeItem id="posts-id" value={{ id: "posts-id", name: "id" }}>
                  <TreeItemTrigger>
                    <TreeItemIndicator />
                    <TreeItemIcon>
                      <Key className="size-4 text-amber-500" />
                    </TreeItemIcon>
                    <TreeItemLabel>id (primary key)</TreeItemLabel>
                  </TreeItemTrigger>
                </TreeItem>
                <TreeItem
                  id="posts-user"
                  value={{ id: "posts-user", name: "user_id" }}
                >
                  <TreeItemTrigger>
                    <TreeItemIndicator />
                    <TreeItemIcon>
                      <Link className="size-4 text-orange-500" />
                    </TreeItemIcon>
                    <TreeItemLabel>user_id (foreign key)</TreeItemLabel>
                  </TreeItemTrigger>
                </TreeItem>
                <TreeItem
                  id="posts-title"
                  value={{ id: "posts-title", name: "title" }}
                >
                  <TreeItemTrigger>
                    <TreeItemIndicator />
                    <TreeItemIcon>
                      <Type className="size-4 text-purple-500" />
                    </TreeItemIcon>
                    <TreeItemLabel>title (varchar)</TreeItemLabel>
                  </TreeItemTrigger>
                </TreeItem>
              </TreeItemContent>
            </TreeItem>

            {/* Indexes */}
            <TreeItem id="indexes" value={{ id: "indexes", name: "Indexes" }}>
              <TreeItemTrigger>
                <TreeItemIndicator />
                <TreeItemIcon>
                  <ListTree className="size-4 text-indigo-500" />
                </TreeItemIcon>
                <TreeItemLabel>Indexes</TreeItemLabel>
              </TreeItemTrigger>
              <TreeItemContent>
                <TreeItem
                  id="idx-email"
                  value={{ id: "idx-email", name: "idx_users_email" }}
                >
                  <TreeItemTrigger>
                    <TreeItemIndicator />
                    <TreeItemIcon>
                      <Hash className="size-4 text-gray-500" />
                    </TreeItemIcon>
                    <TreeItemLabel>idx_users_email</TreeItemLabel>
                  </TreeItemTrigger>
                </TreeItem>
                <TreeItem
                  id="idx-created"
                  value={{ id: "idx-created", name: "idx_posts_created" }}
                >
                  <TreeItemTrigger>
                    <TreeItemIndicator />
                    <TreeItemIcon>
                      <Hash className="size-4 text-gray-500" />
                    </TreeItemIcon>
                    <TreeItemLabel>idx_posts_created</TreeItemLabel>
                  </TreeItemTrigger>
                </TreeItem>
              </TreeItemContent>
            </TreeItem>
          </TreeItemContent>
        </TreeItem>

        {/* Infrastructure Section */}
        <TreeItem
          id="infrastructure"
          value={{ id: "infrastructure", name: "Infrastructure" }}
        >
          <TreeItemTrigger>
            <TreeItemIndicator />
            <TreeItemIcon>
              <Server className="size-4 text-slate-600" />
            </TreeItemIcon>
            <TreeItemLabel>Infrastructure</TreeItemLabel>
          </TreeItemTrigger>
          <TreeItemContent>
            <TreeItem id="storage" value={{ id: "storage", name: "Storage" }}>
              <TreeItemTrigger>
                <TreeItemIndicator />
                <TreeItemIcon>
                  <HardDrive className="size-4 text-blue-400" />
                </TreeItemIcon>
                <TreeItemLabel>Storage (256GB SSD)</TreeItemLabel>
              </TreeItemTrigger>
            </TreeItem>
            <TreeItem id="compute" value={{ id: "compute", name: "Compute" }}>
              <TreeItemTrigger>
                <TreeItemIndicator />
                <TreeItemIcon>
                  <Cpu className="size-4 text-green-500" />
                </TreeItemIcon>
                <TreeItemLabel>Compute (4 vCPUs)</TreeItemLabel>
              </TreeItemTrigger>
            </TreeItem>
            <TreeItem
              id="monitoring"
              value={{ id: "monitoring", name: "Monitoring" }}
            >
              <TreeItemTrigger>
                <TreeItemIndicator />
                <TreeItemIcon>
                  <Activity className="size-4 text-red-500" />
                </TreeItemIcon>
                <TreeItemLabel>Monitoring</TreeItemLabel>
              </TreeItemTrigger>
            </TreeItem>
          </TreeItemContent>
        </TreeItem>

        {/* Settings Section */}
        <TreeItem id="settings" value={{ id: "settings", name: "Settings" }}>
          <TreeItemTrigger>
            <TreeItemIndicator />
            <TreeItemIcon>
              <Settings className="size-4 text-gray-500" />
            </TreeItemIcon>
            <TreeItemLabel>Settings</TreeItemLabel>
          </TreeItemTrigger>
          <TreeItemContent>
            <TreeItem
              id="security"
              value={{ id: "security", name: "Security" }}
            >
              <TreeItemTrigger>
                <TreeItemIndicator />
                <TreeItemIcon>
                  <Shield className="size-4 text-green-600" />
                </TreeItemIcon>
                <TreeItemLabel>Security</TreeItemLabel>
              </TreeItemTrigger>
            </TreeItem>
            <TreeItem
              id="access"
              value={{ id: "access", name: "Access Control" }}
            >
              <TreeItemTrigger>
                <TreeItemIndicator />
                <TreeItemIcon>
                  <Users className="size-4 text-blue-600" />
                </TreeItemIcon>
                <TreeItemLabel>Access Control</TreeItemLabel>
              </TreeItemTrigger>
            </TreeItem>
            <TreeItem
              id="encryption"
              value={{ id: "encryption", name: "Encryption" }}
            >
              <TreeItemTrigger>
                <TreeItemIndicator />
                <TreeItemIcon>
                  <Lock className="size-4 text-amber-600" />
                </TreeItemIcon>
                <TreeItemLabel>Encryption</TreeItemLabel>
              </TreeItemTrigger>
            </TreeItem>
          </TreeItemContent>
        </TreeItem>
      </Tree>
    </div>
  )
}
Multi Select

On This Page

ExampleInstallationUsageProps<TreeItemContent>ExamplesDefaultCustom Icons

Contribute

  • Report an issue
  • Request a feature
  • Edit this page