|
396 | 396 | height: 100%; |
397 | 397 | } |
398 | 398 |
|
| 399 | + #graph-hint { |
| 400 | + position: absolute; |
| 401 | + bottom: 14px; |
| 402 | + left: 50%; |
| 403 | + transform: translateX(-50%); |
| 404 | + background: rgba(30,30,46,0.82); |
| 405 | + color: #94a3b8; |
| 406 | + font-size: 11.5px; |
| 407 | + padding: 5px 12px; |
| 408 | + border-radius: 20px; |
| 409 | + border: 1px solid rgba(148,163,184,0.18); |
| 410 | + pointer-events: none; |
| 411 | + white-space: nowrap; |
| 412 | + z-index: 10; |
| 413 | + backdrop-filter: blur(4px); |
| 414 | + transition: opacity 0.4s; |
| 415 | + } |
| 416 | + |
| 417 | + #graph-hint.hidden { |
| 418 | + opacity: 0; |
| 419 | + } |
| 420 | + |
| 421 | + #graph-hint kbd { |
| 422 | + display: inline-block; |
| 423 | + background: rgba(148,163,184,0.15); |
| 424 | + border: 1px solid rgba(148,163,184,0.3); |
| 425 | + border-radius: 4px; |
| 426 | + padding: 0 5px; |
| 427 | + font-family: inherit; |
| 428 | + font-size: 10.5px; |
| 429 | + line-height: 1.6; |
| 430 | + color: #cbd5e1; |
| 431 | + } |
| 432 | + |
399 | 433 | #detail-panel { |
400 | 434 | width: 380px; |
401 | 435 | background: var(--card-bg); |
@@ -736,6 +770,7 @@ <h1>NLST <span style="color:#818cf8">Sybil</span> Tumor Connectome</h1> |
736 | 770 |
|
737 | 771 | <div id="main-content"> |
738 | 772 | <div id="chart-container"></div> |
| 773 | + <div id="graph-hint"><kbd>click</kbd> node to pin · <kbd>dbl-click</kbd> canvas to unpin · drag to pan · scroll to zoom</div> |
739 | 774 | <button id="shareBtn" class="pulse" onclick="copyShareURL()"> |
740 | 775 | <span class="share-icon">🔗</span> Share URL |
741 | 776 | </button> |
@@ -822,8 +857,14 @@ <h3>How to use it</h3> |
822 | 857 | <li><strong>Model selector:</strong> Choose which AI model's view of tumor similarity to display.</li> |
823 | 858 | <li><strong>Most Similar / Least Similar:</strong> Toggle between seeing the closest or farthest matches.</li> |
824 | 859 | <li><strong>Color by:</strong> Color the dots by clinical features like cancer type, sex, or stage.</li> |
825 | | - <li><strong>Click a dot:</strong> Opens a detail panel showing the patient's clinical data, a CT scan thumbnail, |
826 | | - a link to view the full scan, and their top matches.</li> |
| 860 | + <li><strong>Click a node:</strong> <em>Pins</em> the node — its adjacency highlight stays locked and the detail panel |
| 861 | + opens with the patient's clinical data, a CT scan thumbnail, a link to view the full scan, and their top matches. |
| 862 | + The highlight persists even when you move the mouse away or hover over other nodes.</li> |
| 863 | + <li><strong>Click another node while pinned:</strong> Switches the pin to the new node.</li> |
| 864 | + <li><strong>Double-click anywhere on the graph (not on a node):</strong> <em>Unpins</em> the selection and closes the detail panel.</li> |
| 865 | + <li><strong>× button</strong> in the detail panel: Also unpins and closes the panel.</li> |
| 866 | + <li><strong>Drag:</strong> Pan the graph. Does not unpin.</li> |
| 867 | + <li><strong>Scroll:</strong> Zoom in/out.</li> |
827 | 868 | <li><strong>Share URL:</strong> Copy a link that preserves your current view (model, match type, color, and selected patient).</li> |
828 | 869 | </ul> |
829 | 870 | </div> |
@@ -1619,6 +1660,7 @@ <h3>Data sources</h3> |
1619 | 1660 | clearTimeout(_clickTimer); |
1620 | 1661 | _clickTimer = setTimeout(() => { |
1621 | 1662 | pinnedNode = name; |
| 1663 | + document.getElementById('graph-hint')?.classList.add('hidden'); |
1622 | 1664 | _dispatch({ type: 'downplay', seriesIndex: 0 }); |
1623 | 1665 | _dispatch({ type: 'highlight', seriesIndex: 0, name }); |
1624 | 1666 | showDetailPanel(name); |
|
0 commit comments