fix: referral network rendering — portal fix and visual tuning

Portal to document.body escapes main's contain:content which broke
fixed positioning (container had height:0 and was clipped to main).

Visual fixes for 662+ node graphs:
- labels only on large nodes (threshold 6→14, density 0.5→0.12)
- leaf nodes 5px, referrers 10px, campaigns 16px
- edge opacity reduced to prevent white starburst
- default edge color opacity lowered
This commit is contained in:
c0mrade
2026-03-19 11:12:05 +03:00
parent b787726d1b
commit 2b43a30ccc
3 changed files with 14 additions and 13 deletions

View File

@@ -1,3 +1,4 @@
import { createPortal } from 'react-dom';
import { useTranslation } from 'react-i18next';
import { useQuery } from '@tanstack/react-query';
import { referralNetworkApi } from '@/api/referralNetwork';
@@ -28,7 +29,7 @@ export function ReferralNetwork() {
const isPanelOpen = selectedNode !== null;
return (
return createPortal(
<div
id="referral-network-container"
className="fixed inset-x-0 bottom-0 top-16 z-40 grid grid-rows-[auto_1fr] bg-[#0a0a0f] lg:top-14"
@@ -103,6 +104,7 @@ export function ReferralNetwork() {
)}
</div>
</div>
</div>
</div>,
document.body,
);
}

View File

@@ -21,7 +21,7 @@ function buildFullGraph(graphData: NetworkGraphData): Graph {
label: campaign.name,
x: Math.random() * 100,
y: Math.random() * 100,
size: 24,
size: 16,
color: getCampaignColor(index),
type: 'circle',
nodeType: 'campaign',
@@ -53,8 +53,8 @@ function buildFullGraph(graphData: NetworkGraphData): Graph {
const edgeKey = `${edge.source}->${edge.target}`;
if (!graph.hasEdge(edgeKey)) {
graph.addEdgeWithKey(edgeKey, edge.source, edge.target, {
color: edge.type === 'campaign' ? 'rgba(77, 217, 192, 0.12)' : 'rgba(255,255,255,0.06)',
size: 0.5,
color: edge.type === 'campaign' ? 'rgba(77, 217, 192, 0.06)' : 'rgba(255,255,255,0.03)',
size: 0.3,
edgeType: edge.type,
});
}
@@ -183,14 +183,14 @@ export function NetworkGraph({ data, className }: NetworkGraphProps) {
const sigma = new Sigma(graph, container, {
renderEdgeLabels: false,
labelDensity: 0.5,
labelRenderedSizeThreshold: 6,
labelDensity: 0.12,
labelRenderedSizeThreshold: 14,
zIndex: true,
defaultEdgeColor: '#ffffff10',
defaultEdgeColor: '#ffffff06',
defaultNodeColor: '#6b7280',
labelColor: { color: '#e8e6f0' },
labelFont: 'Inter, system-ui, sans-serif',
labelSize: 12,
labelSize: 11,
stagePadding: 40,
nodeReducer: (node, attrs) => {
const res = { ...attrs };

View File

@@ -46,8 +46,7 @@ export function getUserNodeColor(
* Size is proportional to direct_referrals, clamped between min and max.
*/
export function getUserNodeSize(directReferrals: number): number {
const MIN_SIZE = 12;
const MAX_SIZE = 50;
if (directReferrals === 0) return MIN_SIZE;
return Math.min(MAX_SIZE, MIN_SIZE + Math.sqrt(directReferrals) * 5);
if (directReferrals === 0) return 5;
if (directReferrals <= 2) return 10;
return Math.min(40, 10 + Math.sqrt(directReferrals) * 4);
}