Organigram React provides the React components and hooks of Organigram.ai: diagrams of organizations built on the Organigram Protocol, the screens to propose and decide through procedures, and the chat panel of the workspace agent. It builds on @organigram/js, which reads and writes the contracts.
pnpm add @organigram/react @organigram/js viem recoil react-flow-renderer @mui/material @mui/icons-material react-i18next
The components use MUI for their styles and Recoil for the state they share, so wrap your application in a RecoilRoot and, to get the Organigram look, in a MUI ThemeProvider with theme. The theme expects its fonts at /fonts/*.woff2: copy node_modules/@organigram/react/dist/fonts to the public assets of your application.
Diagram draws an organigram as an interactive graph: organs, procedures and assets are nodes, and the permissions they hold on each other are links. Users can move the nodes, and onNodePositionsChange lets you save their positions. ClassicOrgChart draws the same organigram as a classic tree, where an organ sits below the organ whose members decide on its membership.
Both take an organigram as plain JSON, from organigram.toJson(). Layers, defined by your application, let users show only part of a large organigram: useLayers filters the organigram for either view and remembers the active layers.
procedures holds the screens of each procedure type, by type name: Component describes a procedure, and Proposal shows a proposal with the actions the connected account may take, such as voting or blocking it.
AgentPanel is the chat panel of the workspace agent, including the preview of the changes the agent proposes, which the user confirms or cancels. They only render: your application sends the messages to its agent and stores the conversations. Every text can be replaced through the labels props, to translate them.
import { RecoilRoot } from 'recoil'import { ThemeProvider, createTheme, type ThemeOptions } from '@mui/material/styles'import { Diagram, theme, useOrganigramClient } from '@organigram/react'import { Organigram, getTemplate } from '@organigram/js'import { createPublicClient, http } from 'viem'import { sepolia } from 'viem/chains'const publicClient = createPublicClient({ chain: sepolia, transport: http() })const OrganigramView = () => { const client = useOrganigramClient(publicClient, null, sepolia.id) const organigram = new Organigram(getTemplate('nonProfit', client?.chainId ?? String(sepolia.id))) return <Diagram organigram={organigram.toJson()} controls style={{ height: 600 }} />}export const App = () => ( <RecoilRoot> <ThemeProvider theme={createTheme(theme as ThemeOptions)}> <OrganigramView /> </ThemeProvider> </RecoilRoot>)
We are looking for React developers and testers to keep this project secure and up to date. Please open issues on GitHub, fork the repository and send pull requests.
Diagram draws an organigram as a graph of organs, procedures and assets, linked by the permissions they hold on each other. ClassicOrgChart draws it as a tree of organs and their members. Both take the organigram as plain JSON, from organigram.toJson(), and the node components can be used on their own.
Draw an organigram as an interactive diagram: organs, procedures and assets, linked by the permissions they hold on each other.
<Diagram organigram={organigram.toJson()} onClickOrgan={organ => open(organ)} controls />
const Diagram: React.FC<DiagramProps>
Props accepted by the default Diagram component.
| Property | Type | Description |
|---|---|---|
controls | boolean | Whether to show the zoom controls. |
direction | string | Layout direction: TB from top to bottom, or LR from left to right. |
displayOptions | DiagramDisplayOptions | Which permission links to draw. |
edgeType | OrganigramEdgeType | Line style of the links. |
entryUsers | Record<string, DiagramEntryUser> | Names and avatars of the members, by address. |
isTabletOrAbove | boolean | Whether the screen is at least tablet-sized, to place the controls. |
nodeTypes | NodeTypes | React Flow node components, by node type. Defaults to defaultNodeTypes. |
options | ReactFlowProps | Extra props passed to React Flow. |
organigram | OrganigramJson | null | Organigram to draw, or null while it loads. |
style | Record<string, unknown> | Style of the diagram container. |
Called when the user clicks an asset.
onClickAsset?: (asset: AssetJson) => void;
Called when the user clicks an organ.
onClickOrgan?: (organ: OrganJson) => void;
Called when the user clicks a procedure.
onClickProcedure?: (procedure: ProcedureJson) => void;
Called when the user moves nodes, to save their positions.
onNodePositionsChange?: (nodePositions: OrganigramNodePositions) => void;
Translation function for the labels.
translateLabel?: (label: string) => string;
Draw an organigram as a classic tree of organs and their members, as most people picture an organization chart.
const ClassicOrgChart: React.FC<ClassicOrgChartProps>
Props of ClassicOrgChart.
| Property | Type | Description |
|---|---|---|
controls | boolean | Whether to show the zoom controls. |
isTabletOrAbove | boolean | Whether the screen is at least tablet-sized, to place the controls. |
organigram | OrganigramJson | null | Organigram to draw, or null while it loads. |
style | Record<string, unknown> | Style of the chart container. |
testIdPrefix | string | Prefix of the test identifiers of the nodes. |
Called when the user clicks an organ.
onClickOrgan?: (organ: OrganJson) => void;
Translation function for the labels.
translateLabel?: (label: string) => string;
Default React Flow node used to display one organ inside a diagram.
const OrganNode: React.FC<Partial<NodeProps> & OrganNodeProps>
Props accepted by the default organ node renderer.
| Property | Type | Description |
|---|---|---|
data | { organ: Organ; entryUsers?: Record<string, DiagramEntryUser>; position?: { x: number; y: number; }; isMaster?: boolean; onClick?: () => void; translateLabel?: (label: string) => string; } | The organ, its members' names and avatars, and the click handler. |
hideHandles | boolean | Whether to hide the connection handles, to show the node on its own. |
Name and avatar shown for a member address.
export type DiagramEntryUser = { image?: string | null; name?: string | null;};
Default React Flow node used to display one procedure inside a diagram.
const ProcedureNode: React.FC<Partial<NodeProps<{ procedure: ProcedureJson; onClick?: (procedure: ProcedureJson) => void; organigram?: OrganigramJson; translateLabel?: (label: string) => string;}>> & ProcedureNodeProps>
Props accepted by the default procedure node renderer.
| Property | Type | Description |
|---|---|---|
hideHandles | boolean | Whether to hide the connection handles, to show the node on its own. |
organigram | OrganigramJson | Organigram the procedure belongs to, to name the organs it links. |
Which permission links a diagram draws.
| Property | Type | Description |
|---|---|---|
showAdminPermissions | boolean | Draw the permissions to manage permissions. |
showAssetsPermissions | boolean | Draw the permissions to move funds. |
showEntriesPermissions | boolean | Draw the permissions to change members and documents. |
Read and change the diagram display options, shared across the app.
useDiagramDisplayOptions: () => [DiagramDisplayOptions, SetterOrUpdater<DiagramDisplayOptions>]
Procedure icon.
Procedure: (props: React.SVGProps<SVGSVGElement>) => import("react/jsx-runtime").JSX.Element
Layers are subsets of an organigram defined by your application, such as departments. useLayers filters the organigram for either view according to the layers the user selects, and remembers the selection in a storage you provide.
A named subset of an organigram, such as a department, that users can show or hide.
| Property | Type | Description |
|---|---|---|
assets | ReadonlyArray<{ assetAddress: string; }> | Assets in the layer. |
id | string | Layer identifier. |
organs | ReadonlyArray<{ organAddress: string; }> | Organs in the layer. |
procedures | ReadonlyArray<{ procedureAddress: string; }> | Procedures in the layer. |
A key-value storage for the active layers, such as localStorage.
Read a value.
getItem: (key: string) => string | null;
Write a value.
setItem: (key: string, value: string) => void;
The layers state returned by useLayers.
| Property | Type | Description |
|---|---|---|
activeLayerIds | string[] | Layers currently shown. Empty means everything is shown. |
classicVisibleOrganigram | OrganigramJson | The organigram filtered for ClassicOrgChart. |
visibleOrganigram | OrganigramJson | The organigram filtered for Diagram. |
Show every layer.
showAll: () => void;
Show or hide one layer.
toggleLayer: (layerId: string) => void;
Options of useLayers.
| Property | Type | Description |
|---|---|---|
storage | DiagramLayerStorage | null | Where to remember the active layers, such as localStorage. Without it, the selection is not kept. |
Called when the storage cannot be read or written.
onStorageError?: () => void;
Applies user-selected visual layers to an organigram without owning layer persistence or editing. Applications provide their persisted definitions.
useLayers: (organigram: OrganigramJson, layers: ReadonlyArray<DiagramLayer>, options?: UseLayersOptions) => LayersState
Screens to follow and decide on proposals. procedures gives, for each procedure type, a Component that describes the procedure and a Proposal that shows a proposal with the actions the connected account may take.
Props of the vote components.
| Property | Type | Description |
|---|---|---|
accountInOrgans | { proposers?: boolean; moderators?: boolean; deciders?: boolean; } | Roles of the connected account in the procedure. |
compact | boolean | Whether to use the condensed layout of lists. |
procedure | ERC20VoteProcedure | VoteProcedure | Vote procedure the proposal belongs to. |
proposal | ProcedureProposal | Proposal being voted on. |
publicClient | PublicClient | null | Client used for reads, when the procedure has none. |
voterAddress | string | Address whose vote is shown, by default the connected wallet. |
walletClient | WalletClient | null | Client that signs the vote, when the procedure has none. |
wrapTransaction | TransactionOptions['onTransaction'] | Called with each transaction as soon as it is sent, for example to show its progress. |
Translation function for the labels.
t: (key: string) => string;
Props of the proposal screen of a nomination procedure.
| Property | Type | Description |
|---|---|---|
accountInOrgans | { proposers?: boolean; moderators?: boolean; deciders?: boolean; } | Roles of the connected account in the procedure. |
compact | boolean | Whether to use the condensed layout of lists. |
procedure | NominationProcedure | Nomination procedure the proposal belongs to. |
proposal | ProcedureProposal | Proposal shown. |
publicClient | PublicClient | null | Client used for reads, when the procedure has none. |
walletClient | WalletClient | null | Client that signs the decision, when the procedure has none. |
wrapTransaction | TransactionOptions['onTransaction'] | Called with each transaction as soon as it is sent, for example to show its progress. |
Translation function for the labels.
t: (key: string, options?: any) => string;
UI of each procedure type: Component describes the procedure, Proposal shows a proposal and its decision.
const { Proposal } = procedures[procedure.typeName]
The chat panel of the workspace agent, with the preview of the changes it proposes. These components only render: your application sends the messages to its agent and stores the conversations. Every text can be replaced through the labels props.
Chat panel of the workspace agent: conversations, messages, document upload and proposed changes.
The panel only renders: the application sends the messages and stores the conversations.
Fade and slide its content in and out.
const Animated: React.FC<AnimatedProps>
An answer of the workspace agent.
export type AgentResponse = { threadId?: string; message: string; citations: Citation[]; preview?: OrganigramPreview;};
Props of Animated.
export type AnimatedProps = { visible?: boolean; delay?: number; children: ReactNode; translateY?: number; cursor?: CSSProperties['cursor']; unmountOnExit?: boolean;};
A workspace object the agent refers to in an answer.
export type Citation = { type: 'workspace' | 'organigram' | 'organ' | 'procedure' | 'asset' | 'notification' | 'file'; id: string; label: string;};
Changes the agent proposes to an existing organigram, added to it once confirmed.
export type MergeOrganigramPreview = { type: 'organigram'; organigramId: string; persistence: 'merge-additive'; summary: string[]; organigram: OrganigramJson;};
A message of a conversation with the workspace agent.
export type Message = { role: 'user' | 'assistant'; content: string;};
A new organigram the agent proposes, created once confirmed.
export type NewOrganigramPreview = { type: 'new-organigram'; persistence: 'create'; summary: string[]; organigram: OrganigramJson;};
Changes the agent proposes, which the user confirms or cancels.
export type OrganigramPreview = MergeOrganigramPreview | NewOrganigramPreview;
Texts of the agent panel, to translate it.
export type PanelLabels = PreviewLabels & { title: string; close: string; threads: string; newChat: string; noConversationsYet: string; thinking: string; askPlaceholder: string; attachDocument: string; selectedDocument: string; removeDocument: string; sourceHero: string; sourceWorkspace: string;};
A message shown in the agent panel, possibly still streaming.
export type PanelMessage = Message & { id?: string; response?: AgentResponse; streaming?: boolean;};
Texts of the change preview, to translate it.
export type PreviewLabels = { preview: string; confirmationNotice: string; organ: string; newOrgan: string; newProcedure: string; newAsset: string; newEntry: string; entry: string; organType: string; procedureType: string; assetType: string; cancel: string; confirm: string;};
A saved message of a conversation.
export type StoredMessage = Message & { id: string; createdAt: string; response?: AgentResponse;};
A conversation with the workspace agent.
export type Thread = { id: string; title: string; source: ThreadSource; workspace?: ThreadWorkspace | null; currentOrganigramId?: string | null; createdAt: string; updatedAt: string; messages: StoredMessage[];};
Where a conversation started: in a workspace or on the home page.
export type ThreadSource = 'workspace' | 'hero';
The workspace a conversation belongs to.
export type ThreadWorkspace = { id: string; name?: string | null;};
useOrganigramClient creates an OrganigramClient from your viem clients. The other hooks share state through Recoil, so your application must be wrapped in a RecoilRoot.
Create an OrganigramClient from viem clients, or return null until a public client is available.
The client is created synchronously with the procedure types known for the chain. Use OrganigramClient.load() to read them from chain instead.
const client = useOrganigramClient(publicClient, walletClient, chainId)
useOrganigramClient: (publicClient?: PublicClient | null, walletClient?: WalletClient | null, chainId?: string | number | null) => OrganigramClient | null
React element currently mounted inside the shared modal slot.
export type ModalType = null | JSX.Element;
React state setter signature for the shared modal slot.
export type SetModal = Dispatch<SetStateAction<ModalType>>;
Update the current modal content.
useSetModal: () => SetterOrUpdater<ModalType>
Global recoil state storing the currently opened modal.
const modalState: import('recoil').RecoilState<JSX.Element | null>
Named filters used by proposal list UIs.
export type ProposalFilter = 'current' | 'drafts' | 'passed' | 'blocked' | '';
Check whether the current user belongs to the organ assigned to one procedure role.
isUserInSourceOrgan: (roleType: ProcedureRoleTypeName, organs: OrganJson[], deployedProcedure?: ProcedureJson, userAddress?: string) => boolean
Parameters
| Name | Type | Description |
|---|---|---|
roleType | ProcedureRoleTypeName | Procedure role to inspect. |
organs | OrganJson[] | Hydrated organs available in the current organigram. |
deployedProcedure | ProcedureJson | Procedure whose role organ should be checked. |
userAddress | string | Connected user address. |
The MUI theme of Organigram. Pass it to createTheme() and a ThemeProvider, and serve its fonts from /fonts.
Mobile navigation height used by the hosted Organigram UI.
const mobileNavHeight = 50
Desktop navigation height used by the hosted Organigram UI.
const navHeight = 100
Colors of the Organigram theme.
The MUI theme of Organigram: palette, typography, breakpoints and component styles.
Its fonts are served from /fonts/*.woff2: copy node_modules/@organigram/react/dist/fonts to the public assets of your application.
Fonts and text styles of the Organigram theme.
Workspace navigation height used inside authenticated screens.
const workspaceNavHeight = 60
Edit this page
On this page:
© 2026 Organigram SAS
All Rights Reserved.