Getting Started
Foundations
Components
Search for a command to run...
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.
"use client"
import * as React from "react"
import {
Tree,
TreeItem,
TreeItemContent,
TreeItemIcon,
TreeItemIndicator,
TreeItemLabel,
TreeItemTrigger,
} from "@strongtie/design-system/tree"
import type { TreeItemData } from "@strongtie/design-system/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>
)
}
npm install @strongtie/design-system
import { Tree } from "@strongtie/design-system/tree"<TreeItemContent>| Prop | Type | Default | Description |
|---|---|---|---|
defaultExpanded | string[] | - | |
expanded | string[] | - | |
onExpandedChange | ((expanded: string[]) => void) | - | |
onSelect | ((id: string, item: TreeItemData) => void) | - | |
selected | string | - |
"use client"
import * as React from "react"
import {
Tree,
TreeItem,
TreeItemContent,
TreeItemIcon,
TreeItemIndicator,
TreeItemLabel,
TreeItemTrigger,
} from "@strongtie/design-system/tree"
import type { TreeItemData } from "@strongtie/design-system/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>
)
}
"use client"
import * as React from "react"
import {
Tree,
TreeItem,
TreeItemContent,
TreeItemIcon,
TreeItemIndicator,
TreeItemLabel,
TreeItemTrigger,
} from "@strongtie/design-system/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>
)
}
Components can be styled using the className prop. The design system uses Tailwind CSS for styling.
CSS classes used by this component:
treetree-itemtree-item-contenttree-item-icontree-item-indicatortree-item-labeltree-item-triggerEnsure proper accessibility attributes are added when implementing this component.