Customize Fullscreen Target Container
This example shows how to redirect relation-graph's built-in fullscreen behavior to a larger wrapper element with `fullscreenElementXPath`. A small left-to-right tree sits between an instructional header and two side panels so the fullscreen boundary is obvious and easy to reuse in broader page layouts.
Redirecting Fullscreen to a Page-Level Graph Wrapper
What This Example Builds
This example builds a small left-to-right tree inside a full-page wrapper that also contains explanatory text and two fixed side panels. The visible screen is intentionally simple: a header, a green info callout, the graph in the center, and placeholder blocks on the left and right.
The user can click nodes and use the built-in relation-graph toolbar. The important interaction is the fullscreen button, because this demo makes fullscreen include the surrounding wrapper content instead of isolating only the graph canvas.
The main point is not the tree itself. The main point is how to keep adjacent page UI visible when relation-graph enters fullscreen mode.
How the Data Is Organized
The graph data is declared inline inside initializeGraph() as one RGJsonData object with rootId: 'a', a flat nodes array, and a flat lines array. It describes a compact branching tree with 16 nodes and 15 links.
Before loading the data, the code performs one preprocessing step: it assigns line-${index} to any line that does not already have an id. After that, the dataset is passed directly to setJsonData() with no fetch step, adapter layer, or derived view model.
In a real application, the same structure could represent an approval chain, a component dependency tree, an organizational branch, or any other small relationship set that needs to appear inside a larger page layout.
How relation-graph Is Used
index.tsx wraps the example in RGProvider, and MyGraph.tsx retrieves the active graph instance through RGHooks.useGraphInstance(). A mount-only useEffect() runs initializeGraph(), then loads the inline dataset and normalizes the viewport with setJsonData(), moveToCenter(), and zoomToFit().
The graph itself is configured as a left-to-right tree with layoutName: 'tree', from: 'left', treeNodeGapH: 120, and treeNodeGapV: 10. Default nodes are rectangular 100x30 blocks, lines use RGLineShape.StandardCurve, junction points use RGJunctionPoint.lr, and the expand holder position is set to the right.
The most important option is fullscreenElementXPath: '#my-fullscreen-content'. That tells relation-graph’s built-in fullscreen action to target the outer wrapper element rather than the graph element alone, so the header and both side panels are pulled into fullscreen together with the graph.
No custom slots, editing APIs, or custom toolbar logic appear in this example. The local SCSS file only contains empty selector scaffolding, so the visible result comes from the graph options and the surrounding flex layout rather than from heavy style overrides.
Key Interactions
- Clicking the built-in toolbar fullscreen button switches the entire
#my-fullscreen-contentwrapper into fullscreen, so the header and both side panels stay visible with the graph. - Clicking a node triggers
onNodeClickand logs the node text. It does not change the rendered UI, so node inspection is secondary to the fullscreen lesson.
Key Code Fragments
This wrapper shows that the whole demo runs inside one relation-graph provider context.
const Demo = () => {
return (
<RGProvider>
<MyGraph />
</RGProvider>
);
};
This options block proves that the graph stays simple while fullscreen is redirected to a larger DOM container.
const graphOptions: RGOptions = {
layout: {
layoutName: 'tree',
from: 'left',
treeNodeGapH: 120,
treeNodeGapV: 10
},
fullscreenElementXPath: '#my-fullscreen-content',
debug: false
};
This fragment shows that the example builds its RGJsonData inline as flat nodes and lines.
const myJsonData: RGJsonData = {
rootId: 'a',
nodes: [
{ id: 'a', text: 'a' },
{ id: 'b', text: 'b' },
{ id: 'b1', text: 'b1' }
],
lines: [
{ from: 'a', to: 'b' },
{ from: 'b', to: 'b1' }
]
};
This preprocessing step backfills missing line ids before the dataset is loaded.
myJsonData.lines.forEach((line, index) => {
if (!line.id) {
line.id = `line-${index}`;
}
});
This initialization sequence is the complete graph-instance workflow after the data object is prepared.
await graphInstance.setJsonData(myJsonData);
graphInstance.moveToCenter();
graphInstance.zoomToFit();
This layout fragment shows that the fullscreen target is a page-level wrapper containing instructional content and side panels, not only the RelationGraph component.
<div className="my-graph bg-white" id="my-fullscreen-content">
<div className="flex flex-col" style={{ height: '100vh' }}>
<div className="border-b">
<div className="p-4 text-xs">
<div className="font-bold text-sm">Customize the fullscreen display content using the fullscreenElementXPath option.</div>
</div>
</div>
<div className="grow flex">
<div className="bg-pink-200 w-36 shrink-0 flex place-items-center justify-center border-r border-gray-300">Left</div>
<RelationGraph options={graphOptions} onNodeClick={onNodeClick} />
<div className="bg-blue-200 w-36 shrink-0 flex place-items-center justify-center border-l border-gray-300">Right</div>
</div>
</div>
</div>
What Makes This Example Distinct
The comparison data makes the main distinction clear: this example is not primarily about tree layout, imperative graph control, or slot placement. Its distinctive lesson is that relation-graph fullscreen can be redirected to an outer wrapper so surrounding page content remains part of the fullscreen experience.
Compared with graph-instance-api, it uses a very similar provider-and-instance setup and a similar tree scaffold, but it does much less with graph state after load. Compared with adv-hide-2-show, it is not about delayed mounting inside a hidden container. Compared with built-in-slots, the auxiliary UI is ordinary page-level sibling DOM outside RelationGraph, not HTML injected into graph-owned view or canvas layers.
That combination of a plain three-column wrapper, a small left-to-right tree, and fullscreenElementXPath makes this example a stronger starting point when the real requirement is “my graph sits inside a broader page, and fullscreen should include that broader page.”
Where Else This Pattern Applies
This pattern transfers well to architecture viewers with persistent legends, case-review screens with evidence sidebars, org-tree pages with summary panels, and monitoring dashboards with header instructions or filters. In each of those migration scenarios, the graph can stay technically simple while fullscreen still respects the surrounding layout.
It also applies to documentation and onboarding screens where the graph needs explanatory copy next to it. The reusable idea is to choose one wrapper that contains every UI element that should remain visible after fullscreen begins, then point fullscreenElementXPath at that wrapper.