- AEAmy ElsnerFounder & CEO
- AJAsiya JavayantProduct Lead
- AFAnna FaliUX Designer
- BDBernardo DominicProduct Manager
- OLOnyama LimbaEngineering Lead
- ESElwin SharvillFrontend Engineer
- SSStephen ShawBackend Engineer
Usage#
import { OrgChart } from '@primereact/ui/orgchart';<OrgChart.Root value={data}>
<OrgChart.List />
</OrgChart.Root>Examples#
Basic#
Displays hierarchical data as an interactive tree of nodes.
- Founder
- Product Lead
- UX/UI Designer
- Product Manager
- Engineering Lead
- Frontend Developer
- Backend Developer
'use client';
import { OrgChart } from '@primereact/ui/orgchart';
const data = [
{
key: '0',
label: 'Founder',
children: [
{
key: '0-0',
label: 'Product Lead',
children: [
{
key: '0-0-0',
label: 'UX/UI Designer'
},
{
key: '0-0-1',
label: 'Product Manager'
}
]
},
{
key: '0-1',
label: 'Engineering Lead',
children: [
{
key: '0-1-0',
label: 'Frontend Developer'
},
{
key: '0-1-1',
label: 'Backend Developer'
}
]
}
]
}
];
export default function BasicDemo() {
return (
<div className="flex items-center justify-center">
<OrgChart.Root value={data}>
<OrgChart.List />
</OrgChart.Root>
</div>
);
}
Collapsible#
Use the collapsible prop to make nodes collapsible.
- Founder
- Product Lead
- UX/UI Designer
- Product Manager
- Engineering Lead
- Frontend Developer
- Backend Developer
'use client';
import { OrgChart } from '@primereact/ui/orgchart';
const data = [
{
key: '0',
label: 'Founder',
children: [
{
key: '0-0',
label: 'Product Lead',
children: [
{
key: '0-0-0',
label: 'UX/UI Designer'
},
{
key: '0-0-1',
label: 'Product Manager'
}
]
},
{
key: '0-1',
label: 'Engineering Lead',
children: [
{
key: '0-1-0',
label: 'Frontend Developer'
},
{
key: '0-1-1',
label: 'Backend Developer'
}
]
}
]
}
];
function CollapsibleDemo() {
return (
<div className="flex items-center justify-center">
<OrgChart.Root value={data} collapsible>
<OrgChart.List />
</OrgChart.Root>
</div>
);
}
export default CollapsibleDemo;
Selectable#
Use the selectable prop to make nodes selectable. Besides, use the selectionMode prop to specify the selection mode.
- Founder
- Product Lead
- UX/UI Designer
- Product Manager
- Engineering Lead
- Frontend Developer
- Backend Developer
'use client';
import { OrgChart } from '@primereact/ui/orgchart';
const data = [
{
key: '0',
label: 'Founder',
children: [
{
key: '0-0',
label: 'Product Lead',
children: [
{
key: '0-0-0',
label: 'UX/UI Designer'
},
{
key: '0-0-1',
label: 'Product Manager'
}
]
},
{
key: '0-1',
label: 'Engineering Lead',
children: [
{
key: '0-1-0',
label: 'Frontend Developer'
},
{
key: '0-1-1',
label: 'Backend Developer'
}
]
}
]
}
];
function SelectableDemo() {
return (
<div className="flex items-center justify-center">
<OrgChart.Root value={data} selectable selectionMode="multiple">
<OrgChart.List />
</OrgChart.Root>
</div>
);
}
export default SelectableDemo;
Partial Collapsible & Selectable#
Use the collapsible attribute on a node to make a node collapsible and the selectable attribute on a node to make a node selectable partially.
- Founder
- Product Lead
- UX/UI Designer
- Product Manager
- Engineering Lead
- Frontend Developer
- Backend Developer
'use client';
import { OrgChart } from '@primereact/ui/orgchart';
const data = [
{
key: '0',
label: 'Founder',
collapsible: true,
selectable: false,
children: [
{
key: '0-0',
label: 'Product Lead',
children: [
{
key: '0-0-0',
label: 'UX/UI Designer',
selectable: false
},
{
key: '0-0-1',
label: 'Product Manager'
}
]
},
{
key: '0-1',
label: 'Engineering Lead',
selectable: false,
collapsible: true,
children: [
{
key: '0-1-0',
label: 'Frontend Developer'
},
{
key: '0-1-1',
label: 'Backend Developer'
}
]
}
]
}
];
function PartialDemo() {
return (
<div className="flex items-center justify-center">
<OrgChart.Root value={data}>
<OrgChart.List />
</OrgChart.Root>
</div>
);
}
export default PartialDemo;
Default Collapsed & Selected#
Use the collapsedByDefault attribute on a node to make a node collapsed by default and the selectedByDefault attribute on a node to make a node selected by default.
- Founder
- Product Lead
- Engineering Lead
- Frontend Developer
- Backend Developer
'use client';
import { OrgChart } from '@primereact/ui/orgchart';
const data = [
{
key: '0',
label: 'Founder',
children: [
{
key: '0-0',
label: 'Product Lead',
collapsedByDefault: true,
children: [
{
key: '0-0-0',
label: 'UX/UI Designer'
},
{
key: '0-0-1',
label: 'Product Manager'
}
]
},
{
key: '0-1',
label: 'Engineering Lead',
children: [
{
key: '0-1-0',
label: 'Frontend Developer',
selectedByDefault: true
},
{
key: '0-1-1',
label: 'Backend Developer'
}
]
}
]
}
];
function DefaultDemo() {
return (
<div className="flex items-center justify-center">
<OrgChart.Root value={data} collapsible>
<OrgChart.List />
</OrgChart.Root>
</div>
);
}
export default DefaultDemo;
Custom#
Use the custom attribute on a node to render a custom node content.
- Acme StackProduction technologies
- FrontendUser-facing apps
- React
- Next.js
- BackendAPIs & services
- Postgres
- Redis
- DevOpsBuild & deploy
- Docker
- Kubernetes
'use client';
import { TreeNode } from 'primereact/orgchart';
import { OrgChart } from '@primereact/ui/orgchart';
interface CustomNodeProps extends TreeNode {
data: {
title: string;
description: string;
};
}
const CustomNode = ({ node }: { node: CustomNodeProps }) => {
return (
<div className="flex flex-col items-start gap-1 px-1">
<span className="font-semibold text-sm">{node.data.title}</span>
<span className="text-xs opacity-75">{node.data.description}</span>
</div>
);
};
const data: TreeNode[] = [
{
key: '0',
type: 'service',
htmlProps: {
className:
'border-amber-500 text-amber-900 dark:text-amber-50 bg-amber-500/5 data-selected:text-amber-50 hover:bg-amber-500/15 data-selected:bg-amber-500'
},
data: {
title: 'Acme Stack',
description: 'Production technologies'
},
render: (node: TreeNode) => <CustomNode node={node as CustomNodeProps} />,
children: [
{
key: '0_0',
type: 'service',
htmlProps: {
className:
'border-rose-500 text-rose-900 dark:text-rose-50 bg-rose-500/5 data-selected:text-rose-50 hover:bg-rose-500/15 data-selected:bg-rose-500'
},
data: {
title: 'Frontend',
description: 'User-facing apps'
},
render: (node: TreeNode) => <CustomNode node={node as CustomNodeProps} />,
children: [
{ key: '0_0_0', label: 'React' },
{ key: '0_0_1', label: 'Next.js' }
]
},
{
key: '0_1',
type: 'service',
htmlProps: {
className:
'border-emerald-500 text-emerald-900 dark:text-emerald-50 bg-emerald-500/5 data-selected:text-emerald-50 hover:bg-emerald-500/15 data-selected:bg-emerald-500'
},
data: {
title: 'Backend',
description: 'APIs & services'
},
render: (node: TreeNode) => <CustomNode node={node as CustomNodeProps} />,
children: [
{ key: '0_1_0', label: 'Postgres' },
{ key: '0_1_1', label: 'Redis' }
]
},
{
key: '0_2',
type: 'service',
htmlProps: {
className:
'border-blue-500 text-blue-900 dark:text-blue-50 bg-blue-500/5 data-selected:text-blue-50 hover:bg-blue-500/15 data-selected:bg-blue-500'
},
data: {
title: 'DevOps',
description: 'Build & deploy'
},
render: (node: TreeNode) => <CustomNode node={node as CustomNodeProps} />,
children: [
{ key: '0_2_0', label: 'Docker' },
{ key: '0_2_1', label: 'Kubernetes' }
]
}
]
}
];
function CustomDemo() {
return (
<div className="flex items-center justify-center">
<OrgChart.Root value={data} collapsible>
<OrgChart.List />
</OrgChart.Root>
</div>
);
}
export default CustomDemo;
Template#
- AWS Cloudus-east-1
- ComputeWorkloads & runtime
- EC2Virtual servers
- LambdaServerless functions
- StorageData persistence
- S3Object storage
- RDSManaged databases
- NetworkingEdge & access
- CloudFrontGlobal CDN
- IAMAccess policies
'use client';
import { Bolt } from '@primeicons/react/bolt';
import { Box } from '@primeicons/react/box';
import { Cloud } from '@primeicons/react/cloud';
import { Database } from '@primeicons/react/database';
import { Globe } from '@primeicons/react/globe';
import { Server } from '@primeicons/react/server';
import { Shield } from '@primeicons/react/shield';
import { OrgChartSubtreeInstance, TreeNode } from '@primereact/types/primitive/orgchart';
import { OrgChart } from '@primereact/ui/orgchart';
import * as React from 'react';
interface ServiceNode extends TreeNode {
label: string;
description: string;
icon: React.ComponentType<{ className?: string }>;
accent: string;
children?: ServiceNode[];
}
const data: ServiceNode[] = [
{
key: '0',
label: 'AWS Cloud',
description: 'us-east-1',
icon: Cloud,
accent: 'bg-orange-500/10 text-orange-500',
children: [
{
key: '0_0',
label: 'Compute',
description: 'Workloads & runtime',
icon: Server,
accent: 'bg-sky-500/10 text-sky-500',
children: [
{
key: '0_0_0',
label: 'EC2',
description: 'Virtual servers',
icon: Server,
accent: 'bg-sky-500/10 text-sky-500'
},
{
key: '0_0_1',
label: 'Lambda',
description: 'Serverless functions',
icon: Bolt,
accent: 'bg-sky-500/10 text-sky-500'
}
]
},
{
key: '0_1',
label: 'Storage',
description: 'Data persistence',
icon: Database,
accent: 'bg-emerald-500/10 text-emerald-500',
children: [
{
key: '0_1_0',
label: 'S3',
description: 'Object storage',
icon: Box,
accent: 'bg-emerald-500/10 text-emerald-500'
},
{
key: '0_1_1',
label: 'RDS',
description: 'Managed databases',
icon: Database,
accent: 'bg-emerald-500/10 text-emerald-500'
}
]
},
{
key: '0_2',
label: 'Networking',
description: 'Edge & access',
icon: Globe,
accent: 'bg-violet-500/10 text-violet-500',
children: [
{
key: '0_2_0',
label: 'CloudFront',
description: 'Global CDN',
icon: Globe,
accent: 'bg-violet-500/10 text-violet-500'
},
{
key: '0_2_1',
label: 'IAM',
description: 'Access policies',
icon: Shield,
accent: 'bg-violet-500/10 text-violet-500'
}
]
}
]
}
];
const RecursiveTree = ({ items, root }: { items: ServiceNode[]; root?: boolean }) => {
return (
<OrgChart.Subtree root={root}>
{({ orgchart }: OrgChartSubtreeInstance) =>
items?.map((item) => {
const Icon = item.icon;
return (
<OrgChart.Tree key={item.key} item={item}>
<OrgChart.Node>
<OrgChart.NodeContent>
<div className="flex items-center gap-2">
<div className={`size-9 rounded-md flex items-center justify-center shrink-0 ${item.accent}`}>
<Icon className="size-4!" />
</div>
<div className="flex flex-col items-start gap-0.5">
<div className="text-sm font-semibold leading-none">{item.label}</div>
<div className="text-xs leading-none opacity-75">{item.description}</div>
</div>
</div>
</OrgChart.NodeContent>
<OrgChart.CollapseButton />
</OrgChart.Node>
{item.children && item.children.length > 0 && !orgchart?.isCollapsed(item) && <RecursiveTree items={item.children} />}
</OrgChart.Tree>
);
})
}
</OrgChart.Subtree>
);
};
export default function TemplateDemo() {
return (
<div className="flex items-center justify-center">
<OrgChart.Root collapsible value={data}>
<OrgChart.List>
<RecursiveTree items={data} root />
</OrgChart.List>
</OrgChart.Root>
</div>
);
}
Accessibility#
Screen Reader#
OrgChart uses ARIA roles and attributes for screen reader accessibility. The root element has role="tree" with aria-multiselectable for multiple selection support. Each tree item uses role="treeitem" with aria-level for hierarchy, aria-expanded for collapse state, and aria-selected for selection state. Child nodes are grouped with role="group".
Keyboard Navigation#
OrgChart.Node
| Key | Function |
|---|---|
tab | Moves focus through the focusable nodes within the chart. |
enter | Toggles the selection state of a node. |
space | Toggles the selection state of a node. |
OrgChart.CollapseButton
| Key | Function |
|---|---|
tab | Moves focus through the focusable elements within the chart. |
enter | Toggles the expanded state of a node. |
space | Toggles the expanded state of a node. |