[{"data":1,"prerenderedAt":7},["ShallowReactive",2],{"example-markdown-content:en:graph-canvas-theme-switcher":3},{"markdown":4,"isPaidExample":5,"isTruncated":5,"charLimit":6},"# Switching Relation Graph Canvas Themes with One Wrapper Class\n\n## What This Example Builds\n\nThis example renders a small left-to-right tree and lets the user switch the entire graph presentation among three visual themes at runtime. The graph data and the `RelationGraph` renderer stay the same, but the outer wrapper class changes from `my-graph-theme-1` to `my-graph-theme-3`, which restyles the map background, toolbar, nodes, and checked-state surfaces.\n\nThe screen is a full-height viewer with a floating utility window above the canvas. Users can drag that window, minimize it, open a settings overlay, change the active theme, adjust wheel and canvas-drag behavior through the shared settings panel, and download the current graph as an image.\n\nThe most important idea is that this is a CSS skinning pattern, not a custom rendering pattern. The example keeps a standard tree graph and uses SCSS selectors against relation-graph's built-in DOM structure to create very different visual moods.\n\n## How the Data Is Organized\n\nThe data is declared inline inside `initializeGraph()` as an `RGJsonData` object. It uses one `rootId`, a flat `nodes` array with `id` and `text`, and a flat `lines` array with explicit `id`, `from`, and `to` fields.\n\nThere is no preprocessing step before layout. The code sends the JSON directly to `graphInstance.setJsonData()`, then recenters and fits the result with `moveToCenter()` and `zoomToFit()`.\n\nThis structure is easy to replace with real business data. The same shape could represent an organization tree, a service dependency hierarchy, a category tree, a team ownership map, or an approval chain where each node only needs a label and each edge only needs a source and target.\n\n## How relation-graph Is Used\n\n`index.tsx` wraps the demo in `RGProvider`, so both the main graph component and the shared helper window can resolve the active graph context. Inside `MyGraph.tsx`, `RelationGraph` is rendered once with a compact `graphOptions` object and no custom node slots.\n\nThe layout is a built-in tree layout that grows from left to right, with `treeNodeGapH: 200` and `treeNodeGapV: 10`. The base options intentionally keep the node and line styling neutral: nodes are rectangular, transparent, and lightly bordered; lines use a standard curve shape with left-right junction points; and the toolbar is placed horizontally at the bottom center. That combination leaves room for the imported theme files to define most of the visible chrome.\n\nThe example uses `RGHooks.useGraphInstance()` in two places. In `MyGraph`, it loads the static JSON data and then recenters and fits the graph on mount. In the shared `CanvasSettingsPanel`, it updates runtime options such as `wheelEventAction` and `dragEventAction`, and it runs the image export flow through `prepareForImageGeneration()` and `restoreAfterImageGeneration()`.\n\nStyling is the real focus. Each imported SCSS file targets relation-graph selectors such as `.rg-map`, `.rg-toolbar`, `.rg-node`, `.rg-node-peel.rg-node-checked`, and `.rg-line`. Because the wrapper class changes at the top level, the same graph instance can switch among a radial gradient glass theme, an animated multicolor theme, and an animated diagonal gradient theme without changing the dataset or rebuilding node content.\n\n## Key Interactions\n\nThe main interaction is theme switching. Clicking one of the three `SimpleUISelect` items updates React state, which replaces the wrapper class and immediately reskins the graph.\n\nThe floating helper window is also interactive. It can be dragged around the page, minimized, and expanded again, which keeps the graph itself uncluttered while leaving controls available.\n\nThe settings button opens the shared `CanvasSettingsPanel`. From there, users can switch the mouse wheel between scroll, zoom, and none; switch canvas dragging between selection, move, and none; and download the currently styled canvas as an image. Those controls are generic helper behavior reused across demos, but they are available in this example and affect the live graph instance.\n\nThe theme styles also define checked-state overrides for nodes and lines. The example does not add custom selection logic, but built-in checked visuals can still inherit the active theme styles when relation-graph applies those classes.\n\n## Key Code Fragments\n\nThis options block shows that the graph keeps a simple tree configuration and leaves much of the final appearance to CSS.\n\n```tsx\nconst graphOptions: RGOptions = {\n    defaultLineColor: 'rgba(255, 255, 255, 0.6)',\n    defaultNodeColor: 'transparent',\n    defaultNodeBorderWidth: 1,\n    defaultNodeBorderColor: 'rgba(255, 255, 255, 0.3)',\n    defaultNodeShape: RGNodeShape.rect,\n    defaultNodeWidth: 170,\n    defaultNodeHeight: 40,\n    toolBarDirection: 'h',\n    toolBarPositionH: 'center',\n    toolBarPositionV: 'bottom',\n    defaultPolyLineRadius: 10,\n```\n\nThis initialization sequence proves that the example uses plain `RGJsonData` and the graph instance API instead of a custom loader.\n\n```tsx\nconst myJsonData: RGJsonData = {\n    rootId: 'a',\n    nodes: [\n        { id: 'a', text: 'a' }, { id: 'b', text: 'b' }, { id: 'b1', text: 'b1' },\n        // ...\n    ],\n    lines: [\n        { id: 'l1', from: 'a', to: 'b' }, { id: 'l2', from: 'b', to: 'b1' },\n        // ...\n    ]\n};\n\nawait graphInstance.setJsonData(myJsonData);\ngraphInstance.moveToCenter();\ngraphInstance.zoomToFit();\n```\n\nThis render block shows that live theme switching is only a state change on the wrapper class plus a small selector UI.\n\n```tsx\n\u003Cdiv className={myGraphClassName} style={{ height: '100vh' }}>\n    \u003CDraggableWindow>\n        \u003CSimpleUISelect\n            data={[\n                { value: 'my-graph-theme-1', text: 'Canvas Theme 1' },\n                { value: 'my-graph-theme-2', text: 'Canvas Theme 2' },\n                { value: 'my-graph-theme-3', text: 'Canvas Theme 3' }\n            ]}\n            currentValue={myGraphClassName}\n            onChange={(newValue: string) => {\n                setMyGraphClassName(newValue);\n            }}\n        />\n    \u003C/DraggableWindow>\n```\n\nThis theme fragment shows how the wrapper class reaches into relation-graph's built-in surfaces instead of replacing them with custom slots.\n\n```scss\n.my-graph-theme-2 {\n    .relation-graph {\n        .rg-map {\n            background: radial-gradient(circle at center, #aff69e 0%, #9ed8f6 10%, #f69ee5 20%, #d4980e 30%, #daa93a 40%, #3eda3a 50%, #b9ed94 60%);\n            background-size: 1000% 1000%;\n            animation: backgroundGradient 30s ease infinite;\n        }\n\n        .rg-toolbar {\n            background-color: #ffffff;\n        }\n```\n\nThis helper fragment shows that the settings overlay directly updates graph interaction modes and triggers image export through the shared graph instance.\n\n```tsx\n\u003CSettingRow\n    label=\"Wheel Event:\"\n    options={[\n        { label: 'Scroll', value: 'scroll' },\n        { label: 'Zoom', value: 'zoom' },\n        { label: 'None', value: 'none' },\n    ]}\n    value={wheelMode}\n    onChange={(newValue: string) => { graphInstance.setOptions({ wheelEventAction: newValue }); }}\n/>\n\u003CSettingRow\n    label=\"Canvas Drag Event:\"\n```\n\n## What Makes This Example Distinct\n\nThe comparison data places this demo close to `css-theme`, `generate-image-with-background`, `node-style3`, and `node-drag-handle`, but its emphasis is narrower than any of those neighbors. Its distinct value is showing that one relation-graph tree can switch among three imported full-canvas skins by changing one outer wrapper class while keeping the same data, layout, and built-in renderer.\n\nCompared with `css-theme`, this example is the more focused wrapper-class skinning reference. It does not add a minimap, custom node icon slots, or a larger theme gallery. Instead, it concentrates on atmospheric gradient canvases, translucent rectangular text nodes, and toolbar skinning.\n\nCompared with `generate-image-with-background`, the main lesson is live presentation switching, not a capture-preview workflow. Compared with `node-style3` and `node-drag-handle`, it stays closer to relation-graph's default viewer behavior and uses CSS surface theming as the center of the example rather than slot-driven node content or manual drag interaction.\n\n## Where Else This Pattern Applies\n\nThis pattern transfers well to branded dashboards where the same graph needs multiple visual skins for different customers, campaigns, or workspace modes. It is also a practical fit for white-label products that must preserve one graph implementation while swapping presentation at the CSS layer.\n\nIt also applies to internal tooling that needs temporary presentation modes, such as day versus night operations views, status-themed hierarchy dashboards, or presentation-ready graph screens for demos and screenshots. In those cases, the data model and graph behavior can stay stable while wrapper classes control the visible mood.\n",false,500,1782615434404]