[{"data":1,"prerenderedAt":7},["ShallowReactive",2],{"example-markdown-content:en:node-hover-tooltip":3},{"markdown":4,"isPaidExample":5,"isTruncated":5,"charLimit":6},"# Building a Hover-Only Node Detail Tooltip\n\n## What This Example Builds\n\nThis example builds a read-only relation graph where hovering a custom node opens a small detail card near the pointer. The visible scene is intentionally compact: green circular icon nodes, short labels rendered below the nodes, and a floating white tooltip that stays inside the graph view.\n\nUsers can inspect node details by moving the pointer onto a node and can dismiss the card by leaving that node. Node and line clicks are present, but they only log the selected object, so the main lesson is passive inspection rather than editing or command execution.\n\nThe most useful idea is the split responsibility between the node slot and the view slot: the node slot owns the hover trigger, and the view slot owns the overlay UI.\n\n## How the Data Is Organized\n\nThe graph data is created inline as one `RGJsonData` object inside `initializeGraph()`. It defines `rootId: '2'`, a `nodes` array, and a `lines` array with explicit line ids and labels. Each node also carries `data.myicon`, which the custom node renderer uses to choose a Lucide icon.\n\nThere is no preprocessing step before `setJsonData()`. The component builds the final payload directly in code and loads it as-is, then recenters and fits the viewport. In a business application, the same shape could represent products, services, devices, departments, or dependency items, while `data.myicon` could be replaced by type, status, or category metadata that selects a custom visual.\n\n## How relation-graph Is Used\n\n`index.tsx` wraps the demo with `RGProvider`, and `MyGraph.tsx` calls `RGHooks.useGraphInstance()` to get the live graph instance. A `useEffect()` hook runs `initializeGraph()` after the instance becomes available, which loads the inline data through `setJsonData()` and then calls `moveToCenter()` and `zoomToFit()`.\n\nThe graph options are minimal and visual. `defaultNodeColor` provides the green fill that the custom slot reads through `node.color`, `defaultNodeShape` is set to `RGNodeShape.circle`, and `defaultJunctionPoint` is set to `RGJunctionPoint.border`. The reviewed source does not set an explicit layout option, so the node arrangement depends on relation-graph defaults for this dataset.\n\nThe main customization happens through two slots. `RGSlotOnNode` replaces the built-in node body with a circular icon renderer and binds `onMouseEnter` and `onMouseLeave` directly on the node DOM. `RGSlotOnView` renders the tooltip card as overlay HTML inside the graph scene. The tooltip position is computed from the pointer coordinates relative to a wrapper element, not from a graph event callback.\n\nThe graph-level click events are intentionally secondary. `onNodeClick` and `onLineClick` are bound on `RelationGraph`, but both handlers only log objects to the console. This keeps the demo in viewer mode and makes the hover overlay the only meaningful graph interaction.\n\nLocal styling is light and focused. The SCSS file defines the circular node size and centering through `.c-my-rg-node`, while the tooltip rows use `.c-node-menu-item` for spacing and typography. The overlay itself also sets `pointerEvents: 'none'`, which preserves hover flow on the slotted node instead of turning the card into an interactive menu.\n\n## Key Interactions\n\n- Hovering a node opens a detail tooltip near the current pointer location.\n- Moving the pointer off the node closes the tooltip immediately.\n- The tooltip stays non-interactive because its overlay container disables pointer events.\n- Clicking a node logs the node object but does not change graph state.\n- Clicking a line logs the line object but does not open any additional UI.\n\n## Key Code Fragments\n\nThis options block shows that the example uses relation-graph mostly as a viewer and customizes only the basic node shape, color, and line junction mode.\n\n```tsx\nconst graphOptions: RGOptions = {\n    defaultNodeColor: 'rgba(66,187,66,1)',\n    defaultNodeShape: RGNodeShape.circle,\n    defaultJunctionPoint: RGJunctionPoint.border,\n};\n```\n\nThis inline payload shows that icon selection is driven by per-node metadata and that the graph content is assembled directly in component code.\n\n```tsx\nconst myJsonData: RGJsonData = {\n    rootId: '2',\n    nodes: [\n        { id: '1', text: 'Node-1', data: { myicon: 'star' } },\n        { id: '2', text: 'Node-2', data: { myicon: 'settings' } },\n        // ... more icon-tagged nodes ...\n        { id: '5', text: 'Node-5', data: { myicon: 'gift' } }\n    ],\n    lines: [\n        { id: 'l1', from: '7', to: '71', text: 'Investment' },\n        // ... more labeled lines ...\n    ]\n};\n```\n\nThis initialization sequence proves that the graph instance is loaded through the standard hook-based startup flow.\n\n```tsx\nawait graphInstance.setJsonData(myJsonData);\ngraphInstance.moveToCenter();\ngraphInstance.zoomToFit();\n```\n\nThis hover handler is the key implementation detail for positioning the overlay from wrapper-relative pointer coordinates.\n\n```tsx\nconst showNodeTips = (nodeObject: RGNode, $event: React.MouseEvent) => {\n    setCurrentNode(nodeObject);\n    if (myPage.current) {\n        const _base_position = myPage.current.getBoundingClientRect();\n        setIsShowNodeTipsPanel(true);\n        setNodeMenuPanelPosition({\n            x: $event.clientX - _base_position.x + 10,\n            y: $event.clientY - _base_position.y + 10\n        });\n    }\n};\n```\n\nThis node slot fragment shows that the hover trigger lives on the custom node DOM rather than on a graph-wide mouse-move listener.\n\n```tsx\n\u003CRGSlotOnNode>\n    {({ node }: RGNodeSlotProps) => (\n        \u003Cdiv\n            className=\"h-full\"\n            onMouseEnter={(e) => showNodeTips(node, e)}\n            onMouseLeave={() => hideNodeTips()}\n        >\n            \u003Cdiv className=\"c-my-rg-node\" style={{ backgroundColor: node.color }}>\n                \u003CGetLucideIcon name={node.data?.myicon} />\n            \u003C/div>\n        \u003C/div>\n    )}\n\u003C/RGSlotOnNode>\n```\n\nThis view slot fragment proves that the tooltip is rendered inside the graph scene and deliberately avoids intercepting pointer input.\n\n```tsx\n\u003CRGSlotOnView>\n    {isShowNodeTipsPanel && currentNode && (\n        \u003Cdiv\n            className=\"p-3 bg-white border border-gray-300 shadow-xl absolute rounded-lg\"\n            style={{\n                left: `${nodeMenuPanelPosition.x}px`,\n                top: `${nodeMenuPanelPosition.y}px`,\n                zIndex: 1000,\n                pointerEvents: 'none'\n            }}\n        >\n```\n\n## What Makes This Example Distinct\n\nThe comparison data places this example near `node-menu-2`, `node-menu`, and `node-line-tips-contentmenu`, but it uses the shared slot-overlay building blocks for a narrower purpose. Against `node-menu-2` and `node-menu`, the important difference is that this demo is passive and hover-driven: it does not open actionable menus, it does not branch across node, line, and canvas targets, and it does not need click-away logic for an interactive panel.\n\nCompared with `node-line-tips-contentmenu`, this is the smaller node-only recipe. It does not add line hit-testing, right-click menus, helper windows, or mixed overlay types. The comparison records also emphasize a rare combination here: green circular icon nodes, under-node badge labels, wrapper-relative pointer math, hover enter and leave handlers, and a floating white card with `pointerEvents: 'none'` in an otherwise read-only viewer.\n\nThat makes this example a stronger starting point when the requirement is lightweight node inspection inside the graph scene without introducing menu state, editing flows, or graph mutation. It should not be described as the only overlay demo, but it is one of the clearest references for a non-interactive node-hover detail pattern.\n\n## Where Else This Pattern Applies\n\nThis pattern transfers well to dependency maps, service topology viewers, product relationship explorers, device networks, and organization browsing screens where users need quick read-only details without leaving the graph. The tooltip content can be replaced with health summaries, ownership fields, status metadata, risk labels, or compact metrics while keeping the same hover-trigger and view-overlay structure.\n\nIt is also a practical extension point for richer inspection UI. A team could start with this passive card and later add viewport edge clamping, delayed hover timing, pinned detail panels, or touch-friendly alternatives, while still keeping the base idea of slotted node triggers plus in-scene overlay rendering.\n",false,500,1782615422248]