JavaScript is required

Initially Collapsed Expandable Tree

This example shows how to load a complete tree, collapse selected branches immediately after `setJsonData()`, and reveal them later through node clicks. It is a focused reference for progressive disclosure on a preloaded hierarchy, with automatic relayout and shared canvas settings and export helpers.

Build an Initially Collapsed Tree with Progressive Reveal

What This Example Builds

This example builds a small left-to-right tree viewer that starts in a partially collapsed state. Users see a compact olive-yellow hierarchy with rectangular nodes, orthogonal connectors, and right-side expand holders, then reveal hidden branches by clicking collapsed nodes. The main lesson is not generic tree rendering, but a precise startup flow: load the full dataset once, collapse selected nodes in code, and let the graph behave like a progressive-disclosure explorer.

How the Data Is Organized

The graph data is declared inline as RGJsonData with rootId: 'a', a flat nodes array, and a flat lines array. The example does not use nested children; every relationship is expressed with explicit from and to ids, which makes the collapse step easy to target by node id.

There is one important preprocessing step after setJsonData(): the code looks up a, b, and c with getNodeById() and collapses those nodes before the first stabilized layout. That means the viewer starts from a deliberate disclosure state rather than from the raw fully visible graph.

In production, the same structure can represent organization branches, course outlines, product-category trees, troubleshooting flows, or any hierarchy where the complete graph is already known but should not be shown all at once.

How relation-graph Is Used

The graph uses layoutName: 'tree' with from: 'left', so the hierarchy reads horizontally from left to right. defaultLineShape is RGLineShape.StandardOrthogonal, defaultJunctionPoint is RGJunctionPoint.lr, and defaultExpandHolderPosition is 'right', which keeps the visual language consistent with a horizontal tree. The example also sets matching olive-yellow defaults for nodes and lines, then applies a local SCSS override so node text stays white against the darker fill.

RGHooks.useGraphInstance() is the main integration point. The example uses the graph instance to load the inline data, resolve specific nodes by id, collapse those nodes, run doLayout(), center the result, fit it to the viewport, and later expand collapsed branches from onNodeClick. Because reLayoutWhenExpandedOrCollapsed is enabled in the graph options, branch reveal does not need manual layout code inside the click handler.

There are no custom node, line, canvas, or viewport slots here, and there is no editing workflow. Instead, the surrounding UI comes from a shared DraggableWindow helper. That helper adds a floating description window, a settings overlay backed by RGHooks.useGraphStore(), live setOptions() calls for wheel and drag behavior, and an export flow built on prepareForImageGeneration() and restoreAfterImageGeneration(). Those utilities are useful, but they are shared scaffolding rather than the main distinctive behavior of this demo.

Key Interactions

  • Clicking a node expands it only when node.expanded === false, so the example behaves as a one-way reveal viewer rather than a full click-to-toggle tree.
  • The tree automatically rearranges itself after expand or collapse state changes because reLayoutWhenExpandedOrCollapsed is enabled.
  • The floating helper window can be dragged or minimized, which keeps the explanation and tools available without permanently occupying the canvas.
  • The settings overlay can switch wheel and drag behavior at runtime and download the current graph as an image.

Key Code Fragments

This fragment shows that the demo is configured as a horizontal orthogonal tree with built-in expand holders on the right.

const graphOptions: RGOptions = {
    debug: false,
    layout: {
        layoutName: 'tree',
        from: 'left',
    },
    defaultNodeShape: RGNodeShape.rect,
    defaultLineShape: RGLineShape.StandardOrthogonal,
    defaultJunctionPoint: RGJunctionPoint.lr,
    defaultExpandHolderPosition: 'right',
    reLayoutWhenExpandedOrCollapsed: true,

This fragment proves that the full dataset is loaded first and only then selectively collapsed by node id.

await graphInstance.setJsonData(myJsonData);
['a', 'b', 'c'].forEach(nodeId => {
    const node = graphInstance.getNodeById(nodeId);
    if (node) {
        graphInstance.collapseNode(node);
    }
});

This fragment shows the explicit startup sequence that stabilizes the initial collapsed view before interaction starts.

await graphInstance.doLayout();
graphInstance.moveToCenter();
graphInstance.zoomToFit();

This fragment shows that node clicks only reveal collapsed branches and do not collapse already open ones.

const onNodeClick = async (node: RGNode, $event: RGUserEvent) => {
    const isExpanded = node.expanded;
    if (isExpanded === false) {
        graphInstance.expandNode(node);
    }
};

This fragment shows that the floating settings panel changes relation-graph behavior through live option updates instead of rebuilding the graph.

<SettingRow
    label="Wheel Event:"
    options={[
        { label: 'Scroll', value: 'scroll' },
        { label: 'Zoom', value: 'zoom' },
        { label: 'None', value: 'none' },
    ]}
    value={wheelMode}
    onChange={(newValue: string) => { graphInstance.setOptions({ wheelEventAction: newValue }); }}
/>

What Makes This Example Distinct

This example is distinct because it isolates a very specific disclosure pattern: the entire tree is already present in the initial dataset, selected branches are collapsed immediately after setJsonData(), and the initial view is stabilized before the user starts exploring. That makes it a focused reference for programmatic startup collapse rather than for generic tree rendering.

Compared with open-by-level, it emphasizes branch-by-branch reveal from direct node clicks instead of recomputing disclosure depth for the whole tree. Compared with expand-button, it reveals descendants that are already loaded rather than lazy-loading new child nodes later. Compared with graph-instance-api and tree-data, it goes beyond a plain instance-method demo or a passive tree load by making startup collapse plus node-click reveal the central teaching flow.

The floating helper window and its settings/export controls are useful but not the core differentiator, since that shell is shared by other demos. The strongest combination here is the preloaded flat tree, selective startup collapse, one-way click expansion, and automatic relayout in a compact left-to-right viewer.

Where Else This Pattern Applies

This pattern fits cases where the full hierarchy is already available but showing every branch immediately would overwhelm the user. Good examples include onboarding knowledge maps, department explorers, course-module trees, product-category navigation, and fault-isolation guides.

It also works well when the initial screen should highlight only the main decisions while leaving details discoverable on demand. If a later version needs remote branch loading, this example can serve as the UI baseline before switching the reveal logic to an onNodeExpand data-fetch flow.