---
id: "packages/active-charts/all-exports/org-chart"
title: "OrgChart"
description: "OrgChart, OrgCardField, OrgChartProps, OrgCollapseChange: generated from the source of active-charts."
url: "/packages/active-charts/all-exports/org-chart"
locale: "en"
revision: "g0mvjxwj5c-88bdbe1c:org-chart"
---

# OrgChart

Exported by `@workspace/active-charts`. Generated from the package source; part of [the index of every export](/packages/active-charts/all-exports).

## `OrgChart`

| Prop | Type | Required | Description |
| --- | --- | --- | --- |
| `data` | `HierarchyNode<TExtra>` | yes | Root hierarchy node. Children are nested arbitrarily deep. |
| `height` | `number` | yes | Container height in pixels. Width is always responsive. |
| `accessibility` | `StandaloneAccessibilityOptions` | no | Accessible name, description, data table and keyboard navigation. No `announcements`: it switches `<Chart>`'s interaction announcements, which this family does not make. |
| `animation` | `InteractionAnimationOption` | no | How the tooltip and the context's attention move; the chart has no entrance. `false` turns every interpolation off. |
| `cardFields` | `readonly OrgCardField<TExtra>[]` | no | The lines of a card under the name (T6), in order: at most three fields of `meta`, read by key. Default: `[{key: 'title'}]`, the title line. A card that cannot hold every line leaves out the last ones first; the font never shrinks. Every field stays in the tooltip, the table and the CSV. |
| `className` | `string` | no | Optional className applied to the outer container. |
| `collapsedIds` | `readonly string[]` | no | Controlled: the ids of the collapsed cards. The chart only reports a reader's request through `onCollapsedChange`; ids of no collapsible card are ignored. |
| `collapsible` | `boolean` | no | Let a reader collapse and expand the reports of a card (T6). Off by default: the chart shows the whole tree and no disclosure. A card with reports and an `id` gets a badge with its report count; the badge, and Enter or Space on the focused card, toggle it; the context menu offers Collapse, Expand and Expand all below. A card without an `id` cannot be collapsed, and two nodes with one `id` make the data invalid. The data table and the CSV keep the whole organisation. |
| `colors` | `string[]` | no | Categorical palette for this chart only: replaces the host palette (`--chart-1` … `--chart-10`) in the chart's colour assignment, and nothing else. It is a data encoding, not a theme: surfaces, text, grid and semantic roles keep coming from the CSS token contract, and a series, datum or annotation that sets its own colour keeps it. Any CSS colour string (a public token reference such as `var(--chart-3)`, hex, oklch). |
| `contextMenu` | `FeatureOption<ChartContextMenuOptions<HierarchyElement<TExtra>, "copy" \| "export">>` | no | The context menu. Opened on a node, the host's builder receives a typed {@link HierarchyElement} (`node`, `depth`, `path`; the deepest node under the pointer) as `context.target.element`. |
| `defaultCollapsedIds` | `readonly string[]` | no | Uncontrolled: the ids of the cards collapsed at first. |
| `dir` | `"ltr" \| "rtl"` | no | The chart's UI direction: the reading direction of its HTML text and chrome (tooltip, legend, menus, the accessible table), and the direction the context menu carries under `<body>`.  Left out, the chart inherits the direction of the page around it (the nearest `dir` attribute, else the computed CSS direction) and follows a later change of that attribute. It is never inferred from `locale`, and it never reverses an axis or reorders data: `reversed` stays an explicit axis choice. Under `rtl` the chrome mirrors (legend flow, tooltip side, context menu and submenus, report text in exports), a title-like label starts at the inline start, and a label placed by geometry (an axis tick, a slice or bar label) keeps its physical side; plot arrow keys stay spatial while legend and menu arrows follow the reading direction. |
| `direction` | `"horizontal" \| "vertical"` | no | Layout direction. Default: 'vertical'. |
| `events` | `Omit<ChartEvents, "onLegendChange" \| "onZoomChange">` | no |  |
| `locale` | `ValuePresentation` | no | Presentation input for axis labels, tooltips, labels and accessibility announcements: a locale code (notation follows the language), or a presentation-context object (`{languageLocale, dateShape?, dateFormat?, timeFormat?, numberFormat?, currencyDisplay?}`) carrying language and notation independently. `dateShape` is the normal human date shape a plain date consumer inherits; an axis that declares its own preset for readability keeps it. Forwarded untouched to the central `@workspace/active-format`; the package never resolves tenant or application settings itself. When omitted, `<ChartDefaults>` supplies it; with neither, the chart throws a configuration error (no `'en'` fallback, active-format D14). Object inputs must be referentially stable across renders. |
| `nodeHeight` | `number` | no | Node height in pixels. Default: 60. |
| `nodeSpacingX` | `number` | no | Horizontal spacing between sibling nodes. Default: 20. |
| `nodeSpacingY` | `number` | no | Vertical spacing between levels. Default: 60. |
| `nodeWidth` | `number` | no | Node width in pixels. Default: 140. |
| `onAnimationComplete` | `((event: AnimationCompleteEvent) => void)` | no | Fired when a chart animation completes. - `'load'`: initial mount animation finished (or immediately if animation disabled / prefers-reduced-motion is active). - `'update'`: data-update transition finished.  Not triggered by zoom animations (use `onZoomChange`) or tooltip fades. |
| `onCollapsedChange` | `((collapsedIds: string[], change: OrgCollapseChange) => void)` | no | The collapsed ids a reader asked for, and why (T6). |
| `onExportComplete` | `((result: ChartExportResult) => void)` | no | Fired after a successful export action (PNG/SVG/CSV/PDF), including from the context menu and from imperative `ChartHandle` calls. |
| `onExportError` | `((format: ChartExportFormat, error: unknown) => void)` | no | Fired when an export could not produce its file (W11), from the handle as well as from the context menu. Without it a failed context-menu export is reported as an error diagnostic (`<ChartDefaults diagnostics>`). |
| `onReady` | `(() => void)` | no | Fired exactly once per chart instance, after the first successful mount with valid dimensions and **before** any entrance animation starts. "Ready" means: the SVG is in the DOM, layout has run with real dimensions, and the chart can be queried by integration tests.  Distinct from {@link onAnimationComplete} with `type: 'load'`, which fires *after* the load animation finishes. A chart with `animation={false}` still fires `onReady` — animation state has no effect on readiness.  A new React `key` on the host produces a new component instance and `onReady` fires again. Identity changes of the callback itself after the first fire are ignored (latch is per-instance).  **Consumer requirement — stable from first render.** The latch closes on the first effect run regardless of whether `onReady` was defined at that moment. If `onReady` is initially `undefined` and later resolves to a function, the callback will **never** fire — the latch has already closed with a no-op. Pass a stable reference (typically via `useCallback`) or pass the final function unconditionally from the first render. |
| `ref` | `Ref<ChartExportHandle>` | no | Imperative handle: exports and element access. A family built on this type has no data-range zoom, so its handle has no `setZoom`. Allows getting a ref to the component instance. Once the component unmounts, React will set `ref.current` to `null` (or call the ref with `null` if you passed a callback ref). |
| `t` | `ChartTranslateFn` | no | The host translator for every text the chart shows or announces. When omitted, `<ChartDefaults>` supplies it; with neither, the chart throws a configuration error (no English fallback, ADR-028). |
| `tooltip` | `StandaloneTooltipOption<"valueFormatter">` | no | Tooltip of the node under the pointer: `enabled`, `renderer` and `style`. The card shows the name and title without a value, so no `valueFormatter` (ADR-082, LAB-AT17). |
| `width` | `number` | no | Optional fixed width in pixels. Default: fill container. |
| `zoomControls` | `boolean` | no | Show zoom controls (+, −, percentage, fit-to-screen). Default: true. |

## Types

**OrgCardField**

```ts
interface OrgCardField<
  TExtra extends Record<string, unknown> = Record<string, unknown>,
> {
  key: Extract<keyof TExtra, string>;
  label?: string;
  showLabel?: boolean;
}
```

One line of an org card under the name (T6): a field of the node's
`meta`, by key. A string is shown as it is, a finite number in the
chart's number notation; anything else is no line.

**OrgChartProps**

```ts
interface OrgChartProps<
  TExtra extends Record<string, unknown> = {title?: string},
> extends Omit<HierarchicalChartProps<TExtra>, 'animation' | 'tooltip'> {
  animation?: InteractionAnimationOption;
  tooltip?: StandaloneTooltipOption<'valueFormatter'>;
  direction?: 'vertical' | 'horizontal';
  nodeWidth?: number;
  nodeHeight?: number;
  nodeSpacingX?: number;
  nodeSpacingY?: number;
  zoomControls?: boolean;
  collapsible?: boolean;
  collapsedIds?: readonly string[];
  defaultCollapsedIds?: readonly string[];
  onCollapsedChange?: (
    collapsedIds: string[],
    change: OrgCollapseChange,
  ) => void;
  cardFields?: readonly OrgCardField<TExtra>[];
}
```

Props for {@link OrgChart}. Extends {@link HierarchicalChartProps} for the
wrapper contract (context-driven defaults via `<ChartDefaults>`,
unified event model, colors/accessibility propagation). The `TExtra`
generic defaults to `{title?: string}` because OrgChart rendering reads
`meta.title` for role labels; consumers may widen the shape.

OrgChart has no entrance animation; its `animation` prop times only the
tooltip and the context's attention (ADR-104, W10, ADR-040);
`onAnimationComplete({type: 'load'})` fires on mount. Hover transitions
(120–150ms background/opacity on zoom
controls) are retained as interaction feedback and fall below the WCAG
2.3.3 threshold for reduced-motion concerns; the global media query in
`accessibility.css` suppresses them defensively under
`prefers-reduced-motion: reduce`.

**OrgCollapseChange**

```ts
type OrgCollapseChange =
  | {
      source: ChartInteractionSource;
      id: string;
      collapsed: boolean;
      scope: 'node' | 'subtree';
      requested: boolean;
    }
  | {source: 'update'; removed: string[]; requested: false};
```

Why the collapsed set changed (T6). A reader's request names the card
(`id`), whether the change collapses it, and its input (`source`: a mouse
or pen, a finger or a key; for a menu action the input that opened the
menu); `scope: 'subtree'` is Expand all below. `requested`:
`true` on a controlled chart, whose `collapsedIds` the change only
proposes (the chart draws it once the host passes it back), `false` where
the chart applied it. `'update'`: an uncontrolled set lost ids the data no
longer holds.
