ApexTree - Installation and Getting started

June 24, 2026 · View on GitHub

The Apextree is a javascript library built on SVG that helps to create organizational or hierarchical charts.

Apextree Banner

Installation

To add the Apextree to your project and its dependencies, install the package from npm.

npm install apextree

Usage

import ApexTree from 'apextree';

To create a basic tree with minimal configuration, write as follows:

<div id="svg-tree"></div>
 const data = {
   ...(nested data with format provided below)
 }
 const options = {
   width: 700,
   height: 700,
   nodeWidth: 120,
   nodeHeight: 80,
   childrenSpacing: 100,
   siblingSpacing: 30,
   direction: 'top',
   canvasStyle: 'border: 1px solid black;background: #f6f6f6;',
 };
 const tree = new ApexTree(document.getElementById('svg-tree'), options);
 const graph = tree.render(data);

Setting the License

To use ApexTree with a commercial license, set your license key before creating any chart instances:

import ApexTree from 'apextree';

// set license key before creating any charts
ApexTree.setLicense('your-license-key');

const tree = new ApexTree(document.getElementById('svg-tree'), options);
const graph = tree.render(data);

Tree Options

The layout can be configured by passing a second argument to ApexTree with the properties listed below.

Layout & Canvas

OptionTypeDefaultDescription
widthnumber | string'100%'Width of the canvas. Accepts a pixel number or CSS percentage string.
heightnumber | string'auto'Height of the canvas. 'auto' sizes to content.
viewPortWidthnumber800Internal SVG viewport width in pixels.
viewPortHeightnumber600Internal SVG viewport height in pixels.
direction'top' | 'bottom' | 'left' | 'right''top'Direction the tree grows from the root node.
contentKeystring'name'Key in the data object used as the node display label. Set to 'data' to pass a structured object to nodeTemplate.
siblingSpacingnumber50Horizontal distance between sibling nodes in pixels.
childrenSpacingnumber50Vertical distance between a parent node and its children in pixels.
paddingXnumber100Horizontal padding around the rendered tree, in pixels. Adds breathing room between the leftmost/rightmost nodes (and any external labels that extend past them) and the SVG viewBox edge.
paddingYnumber100Vertical padding around the rendered tree, in pixels. Useful when leaf nodes have rotated externalLabel content that extends past the marker bounds.
canvasStylestring''Arbitrary CSS injected onto the SVG root container element.
containerClassNamestring'root'CSS class name for the root SVG container element.
theme'light' | 'dark' | 'custom''light'Built-in theme preset. 'dark' uses slate backgrounds for dark-mode apps. 'custom' disables built-in CSS variable injection so host-page variables take precedence.

Interaction & Features

OptionTypeDefaultDescription
highlightOnHoverbooleantrueHighlight the hovered node and its connecting edges.
enableAnimationbooleantrueAnimate node expansion/collapse transitions.
enableExpandCollapsebooleantrueShow expand/collapse buttons on nodes that have children.
expandCollapseOnNodeClickbooleanfalseWhen true, clicking anywhere on a node with children toggles its expansion — the node body itself acts as the trigger. Useful for marker-style trees where the dedicated +/- button is hidden. The toggle fires before onNodeClick. The cursor becomes a pointer on clickable nodes.
enableExpandCollapseZoombooleantrueRe-fit the viewBox to the new tree bounds on collapse/expand. Set to false to keep the viewBox fixed.
enableToolbarbooleanfalseShow the zoom/pan toolbar.
enableZoomPanbooleantrueEnable Ctrl/⌘ + mouse-wheel (or trackpad pinch) zoom and drag-to-pan on the canvas. A plain wheel still scrolls the page. Set to false to lock the viewport.
enableSearchbooleanfalseShow a search input in the toolbar. Filters nodes by label, highlights matches, and centers on the first match on Enter.
enableSelection'single' | 'multi' | falsefalseNode selection mode. 'single' allows one selected node at a time. 'multi' allows toggling multiple nodes. Selected nodes get aria-selected="true" and a visible ring.
enableBreadcrumbbooleanfalseShow a breadcrumb trail above the chart. Updates on node click to show the path from root to the selected node.
groupLeafNodesbooleanfalseStack leaf nodes vertically instead of spreading them horizontally.
groupLeafNodesSpacingnumber10Spacing between stacked leaf nodes in pixels.
onNodeClick(node: unknown) => voidundefinedCallback fired when the user clicks a node. Receives the raw node data object.

Node Styling

OptionTypeDefaultDescription
nodeWidthnumber50Width of each node in pixels.
nodeHeightnumber30Height of each node in pixels.
nodeTemplate(content, context?) => stringbuilt-inCustom function returning an HTML string rendered inside each node. Receives the value at contentKey plus a NodeTemplateContext ({ direction, cardImagePosition }).
cardImagePosition'left' | 'top''left'Avatar placement in the built-in org-card. 'top' centers the avatar above the text (and below it for direction: 'bottom', so it faces the parent).
nodeClassNamestring'apextree-node'CSS class name added to every node element.
nodeStylestring''Inline CSS string applied to each node element.
nodeBGColorstring'#FFFFFF'Default background color of nodes.
nodeBGColorHoverstring'#FFFFFF'Background color of nodes on hover.
nodeShadowstring'0 1px 2px rgba(16,24,40,0.06), 0 1px 3px rgba(16,24,40,0.1)'CSS box-shadow applied to nodes. Set to empty string to disable.
nodeShadowHoverstring'0 4px 6px -1px rgba(16,24,40,0.1), 0 2px 4px -2px rgba(16,24,40,0.1)'CSS box-shadow applied to nodes on hover. Set to empty string to keep constant.
borderWidthnumber1Border width of nodes in pixels.
borderStylestring'solid'CSS border-style for nodes.
borderRadiusstring'10px'CSS border-radius for nodes.
borderColorstring'#E4E7EC'Border color of nodes in their default state.
borderColorHoverstring'#5C6BC0'Border color of nodes on hover.
externalLabelExternalLabelOptions{ enabled: false }Render the node's label outside its bounds (above/below/beside the node) instead of inside the nodeTemplate. See External Labels.

External Labels

When externalLabel.enabled is true, the node's resolved content (the value at contentKey, falling back to name for object content) is rendered as an SVG <text> element positioned relative to the node, instead of inside the in-node template. The node box itself still renders, so combining a small nodeWidth/nodeHeight with borderRadius: '50%' produces a circular marker with a floating label — useful for treegraph-style charts where labels sit above, beside, or below the marker.

External labels can be configured globally via the top-level externalLabel option, or per-node via NestedNode.options.externalLabel. Per-node values are layered onto the global ones.

OptionTypeDefaultDescription
externalLabel.enabledbooleanfalseRender the label outside the node bounds. When false, the in-node nodeTemplate is used as before.
externalLabel.align'left' | 'center' | 'right''center'Horizontal placement of the label relative to the node. 'left' places it to the left, 'right' to the right.
externalLabel.verticalAlign'top' | 'middle' | 'bottom''middle'Vertical placement of the label relative to the node. 'top' places it above the node, 'bottom' below.
externalLabel.offsetXnumber0Additional horizontal pixel offset applied after align.
externalLabel.offsetYnumber0Additional vertical pixel offset applied after verticalAlign.
externalLabel.rotationnumber0Rotation in degrees applied around the label anchor. Use 90 for vertical leaf labels.
externalLabel.fontColorstringinherits fontColorOverride the global font color for the external label.
externalLabel.fontFamilystringinherits fontFamilyOverride the global font family for the external label.
externalLabel.fontSizestringinherits fontSizeOverride the global font size for the external label.
externalLabel.fontWeightstringinherits fontWeightOverride the global font weight for the external label.

Edge (Connector) Styling

OptionTypeDefaultDescription
edgeStyle'orthogonal' | 'curved' | 'straight''orthogonal'Shape of connecting lines. 'orthogonal' draws right-angle elbows. 'curved' draws smooth Bézier curves. 'straight' draws direct lines.
edgeWidthnumber1Stroke width of connecting lines in pixels.
edgeColorstring'#D0D5DD'Color of connecting lines between nodes.
edgeColorHoverstring'#5C6BC0'Color of connecting lines when highlighted on hover.
edgeColorMode'default' | 'node''default''default' uses the global edgeColor. 'node' inherits the borderColor of the child node each edge connects into, giving each branch a matching color.

Expand/Collapse Button & Badge

OptionTypeDefaultDescription
expandCollapseButtonBGColorstring'#FFFFFF'Background color of the expand/collapse button.
expandCollapseButtonBorderColorstring'#E4E7EC'Border color of the expand/collapse button.
collapseBadgeEnabledbooleantrueShow the collapse-count badge on collapsed nodes.
collapseBadgeThresholdnumber1Minimum number of hidden children required before the badge appears.
collapseBadgeBGColorstring'#5C6BC0'Background color of the collapse-count badge.
collapseBadgeFontColorstring'#FFFFFF'Font color of the collapse-count badge.
collapseBadgeFontSizestring'12px'Font size of the collapse-count badge.

Typography

OptionTypeDefaultDescription
fontColorstring'#101828'CSS color for node text.
fontFamilystringsystem defaultCSS font-family for node text. Falls back to the page default when empty.
fontSizestring'14px'CSS font-size for node text.
fontWeightstring'400'CSS font-weight for node text.

Tooltip

OptionTypeDefaultDescription
enableTooltipbooleanfalseShow a tooltip on node hover.
tooltipIdstring'apextree-tooltip-container'HTML id for the tooltip container element.
tooltipTemplate(content: string) => stringbuilt-inCustom function returning an HTML string for the tooltip content.
tooltipMaxWidthnumber | undefinedundefinedMaximum width of the tooltip in pixels.
tooltipMinWidthnumber100Minimum width of the tooltip in pixels.
tooltipBorderColorstring'#BCBCBC'Border color of the tooltip.
tooltipBGColorstring'#FFFFFF'Background color of the tooltip.
tooltipFontColorstring'#000000'Font color of tooltip text.
tooltipFontSizestring'12px'Font size of tooltip text.
tooltipPaddingnumber8Inner padding of the tooltip in pixels. Set to 0 when using a custom tooltipTemplate.
tooltipOffsetnumber10Distance between the tooltip and the cursor in pixels.

Accessibility

OptionTypeDefaultDescription
a11y{ enabled?: boolean, label?: string }{ enabled: true, label: 'Organizational chart' }WCAG 2.1 AA accessibility. Adds ARIA tree semantics, keyboard navigation, and visible focus indicators. Set label to customise the SVG aria-label.

Node Templates

Default template

When contentKey is 'name' (the default), the built-in template renders a single centered label:

const defaultNodeTemplate = (content) => {
  return `<div style='display: flex;justify-content: center;align-items: center; text-align: center; height: 100%;'>${content}</div>`;
};

Built-in org-chart card

When contentKey is set to 'data' and the data object contains any of imageURL, title, subtitle, badge, accentColor, or meta, the built-in template automatically renders a structured org-chart card — no custom nodeTemplate needed.

The card supports two layouts via the cardImagePosition option: 'left' (default — avatar beside the text) and 'top' (avatar centered above the text, or below for direction: 'bottom', with accentColor applied as the avatar ring). Optional meta rows render icon + label lines under the title/subtitle.

const data = {
  id: 'ceo',
  name: 'Alice',
  data: {
    name: 'Alice Johnson',
    title: 'Chief Executive Officer',
    subtitle: 'Executive',
    imageURL: 'https://example.com/avatar.jpg',
    accentColor: '#6366f1',
    badge: {text: 'Active', color: '#EEF2FF'},
    // Optional icon + label rows (icon is any icon-font class, or omit it):
    meta: [{icon: 'bi bi-geo-alt', label: 'San Francisco'}, {label: 'Joined 2019'}],
  },
  children: [],
};

const options = {
  contentKey: 'data',
  nodeWidth: 200,
  nodeHeight: 80,
  cardImagePosition: 'top', // avatar centered above the text
};

Custom template

Pass a nodeTemplate function for full control over node rendering:

const options = {
  contentKey: 'data',
  nodeTemplate: (content) => `
    <div style="display: flex; align-items: center; gap: 8px; padding: 8px;">
      <img src="${content.img}" style="width: 32px; height: 32px; border-radius: 50%;" />
      <div>
        <div style="font-weight: 600;">${content.name}</div>
        <div style="font-size: 11px; color: #666;">${content.role}</div>
      </div>
    </div>`,
};

Safari compatibility: ApexTree renders each node's HTML inside an SVG <foreignObject>. When the SVG viewBox is scaled — width: '100%', any zoom level, or mobile fit-to-viewport (which is always scaled) — Safari/WebKit mis-paints any foreignObject descendant that gets its own paint layer or stacking context: the card renders blank, or its content collapses to the canvas origin. Chromium and Firefox are unaffected, so the bug is invisible until a user opens Safari.

Inside a nodeTemplate, avoid every property that creates a paint layer or stacking context:

  • position: relative / absolute / fixed / sticky
  • opacity less than 1
  • transform, filter
  • z-index, will-change, mix-blend-mode, isolation: isolate

Use plain flow with flex/grid layout and DOM order for stacking instead. Dim text with color (e.g. rgba(...) or color-mix(...)), not opacity. Overlap an avatar on the card edge with a negative margin rather than position: absolute. In development, ApexTree inspects your template and logs a one-time console.warn naming any offending property so you can spot this without testing in Safari.

Per-Node Options

Individual nodes can override global styling via an options object. This accepts the same node, font, and tooltip options as the global configuration:

const data = {
  id: 'ceo',
  name: 'CEO',
  options: {
    nodeBGColor: '#EEF2FF',
    nodeBGColorHover: '#EEF2FF',
    borderColor: '#A5B4FC',
    borderColorHover: '#6366F1',
  },
  children: [
    {
      id: 'cto',
      name: 'CTO',
      options: {
        nodeBGColor: '#ECFDF5',
        borderColor: '#6EE7B7',
      },
      children: [],
    },
  ],
};

Expected Data Format

{
  "id": "1",
  "name": "A",
  "children": []
}

Each node object requires:

  • id — unique identifier. Must be unique across all nodes for edge highlighting and selection to work correctly.
  • name — display label rendered inside the node (when using the default contentKey: 'name').
  • children — array of child node objects. Pass an empty array [] for leaf nodes.
  • data (optional) — arbitrary data payload. When using contentKey: 'data', this object is passed to nodeTemplate.
  • options (optional) — per-node style overrides (see Per-Node Options).

Example

const data = {
  id: '1',
  name: 'A',
  children: [
    {
      id: '2',
      name: 'B',
      children: [
        {
          id: '3',
          name: 'C',
          children: [],
        },
        {
          id: '4',
          name: 'D',
          children: [],
        },
      ],
    },
  ],
};

Graph API Methods

The tree.render(data) call returns a graph instance with the following public methods:

Layout & View

MethodDescription
changeLayout(direction)Switch the tree direction dynamically ('top', 'bottom', 'left', 'right').
fitScreen()Re-fit the viewBox to show all visible nodes.
centerOnNode(nodeId)Pan and zoom to center a specific node in the viewport.

Expand & Collapse

MethodDescription
collapse(nodeId)Programmatically collapse a node.
expand(nodeId)Programmatically expand a node.

Selection

MethodDescription
getSelection()Returns an array of currently selected node IDs.
setSelection(ids)Programmatically set selected nodes by ID array.
clearSelection()Clear all selections.
onSelectionChange(listener)Register a callback fired whenever the selection changes. Pass null to remove.
MethodDescription
findNodesByQuery(query)Returns an array of node IDs whose labels match the query string.
setSearchHighlight(matchIds)Highlight specific nodes as search results. Pass an empty array to clear.

Data & Nodes

MethodDescription
construct(data)Replace the tree data and re-render.
getNodeMap()Returns a map of all node IDs to their node objects.
getRootNodeId()Returns the ID of the root node.
getNodeLabel(nodeId)Returns the display label for a node.
MethodDescription
setBreadcrumbHandler(handler)Register a callback for breadcrumb segment clicks. Pass null to remove.

Keyboard Shortcuts

MethodDescription
setKeyboardShortcutHandlers(handlers)Wire up callbacks for keyboard shortcuts that operate outside the tree itself — typically used to focus or clear an external search input. handlers is { onFocusSearch?: () => void, onClearSearch?: () => void }. Handlers persist across render() calls until replaced.

Export

MethodDescription
exportToSvg()Export the current tree as an SVG file download.

Example

const tree = new ApexTree(document.getElementById('svg-tree'), options);
const graph = tree.render(data);

// Change layout direction
graph.changeLayout('left');

// Collapse a node programmatically
graph.collapse('node-2');

// Listen for selection changes
graph.onSelectionChange((ids) => {
  console.log('Selected:', ids);
});

// Search and highlight
const matches = graph.findNodesByQuery('engineer');
graph.setSearchHighlight(matches);
graph.centerOnNode(matches[0]);