diff --git a/frontend/components/screen/ScreenRelationFlow.tsx b/frontend/components/screen/ScreenRelationFlow.tsx index cad4fc1f..a95e05d0 100644 --- a/frontend/components/screen/ScreenRelationFlow.tsx +++ b/frontend/components/screen/ScreenRelationFlow.tsx @@ -35,13 +35,13 @@ import { getTableColumns, ColumnTypeInfo } from "@/lib/api/tableManagement"; import { ScreenSettingModal } from "./ScreenSettingModal"; import { TableSettingModal } from "./TableSettingModal"; -// 관계 유형별 색상 정의 +// 관계 유형별 색상 정의 (CSS 변수 기반 - 다크모드 자동 대응) const RELATION_COLORS: Record = { - filter: { stroke: '#8b5cf6', strokeLight: '#c4b5fd', label: '마스터-디테일' }, // 보라색 - hierarchy: { stroke: '#06b6d4', strokeLight: '#a5f3fc', label: '계층 구조' }, // 시안색 - lookup: { stroke: '#f59e0b', strokeLight: '#fcd34d', label: '코드 참조' }, // 주황색 (기존) - mapping: { stroke: '#10b981', strokeLight: '#6ee7b7', label: '데이터 매핑' }, // 녹색 - join: { stroke: '#f97316', strokeLight: '#fdba74', label: '엔티티 조인' }, // orange-500 (기존 주황색) + filter: { stroke: 'hsl(var(--primary))', strokeLight: 'hsl(var(--primary) / 0.4)', label: '마스터-디테일' }, + hierarchy: { stroke: 'hsl(var(--info))', strokeLight: 'hsl(var(--info) / 0.4)', label: '계층 구조' }, + lookup: { stroke: 'hsl(var(--warning))', strokeLight: 'hsl(var(--warning) / 0.4)', label: '코드 참조' }, + mapping: { stroke: 'hsl(var(--success))', strokeLight: 'hsl(var(--success) / 0.4)', label: '데이터 매핑' }, + join: { stroke: 'hsl(var(--warning))', strokeLight: 'hsl(var(--warning) / 0.4)', label: '엔티티 조인' }, }; // 노드 타입 등록 @@ -689,12 +689,12 @@ function ScreenRelationFlowInner({ screen, selectedGroup, initialFocusedScreenId targetHandle: "left", type: "smoothstep", label: `${i + 1}`, - labelStyle: { fontSize: 11, fill: "#0ea5e9", fontWeight: 600 }, + labelStyle: { fontSize: 11, fill: "hsl(var(--info))", fontWeight: 600 }, labelBgStyle: { fill: "hsl(var(--card))", stroke: "hsl(var(--border))", strokeWidth: 1 }, labelBgPadding: [4, 2] as [number, number], - markerEnd: { type: MarkerType.ArrowClosed, color: "#0ea5e9" }, + markerEnd: { type: MarkerType.ArrowClosed, color: "hsl(var(--info))" }, animated: true, - style: { stroke: "#0ea5e9", strokeWidth: 2 }, + style: { stroke: "hsl(var(--info))", strokeWidth: 2 }, }); } } @@ -712,7 +712,7 @@ function ScreenRelationFlowInner({ screen, selectedGroup, initialFocusedScreenId type: "smoothstep", animated: true, // 모든 메인 테이블 연결은 애니메이션 style: { - stroke: "#3b82f6", + stroke: "hsl(var(--primary))", strokeWidth: 2, }, }); @@ -751,7 +751,7 @@ function ScreenRelationFlowInner({ screen, selectedGroup, initialFocusedScreenId type: "smoothstep", animated: true, style: { - stroke: "#3b82f6", + stroke: "hsl(var(--primary))", strokeWidth: 2, strokeDasharray: "5,5", // 점선으로 필터 관계 표시 }, @@ -1006,10 +1006,10 @@ function ScreenRelationFlowInner({ screen, selectedGroup, initialFocusedScreenId targetHandle: "top", type: "smoothstep", label: rel.relation_type === "join" ? "조인" : rel.crud_operations || "", - labelStyle: { fontSize: 9, fill: "#10b981" }, + labelStyle: { fontSize: 9, fill: "hsl(var(--success))" }, labelBgStyle: { fill: "hsl(var(--card))", stroke: "hsl(var(--border))", strokeWidth: 1 }, labelBgPadding: [3, 2] as [number, number], - style: { stroke: "#10b981", strokeWidth: 1.5 }, + style: { stroke: "hsl(var(--success))", strokeWidth: 1.5 }, }); } } @@ -1029,11 +1029,11 @@ function ScreenRelationFlowInner({ screen, selectedGroup, initialFocusedScreenId type: "smoothstep", animated: true, label: flow.flow_label || flow.flow_type || "이동", - labelStyle: { fontSize: 10, fill: "#8b5cf6", fontWeight: 500 }, + labelStyle: { fontSize: 10, fill: "hsl(var(--primary))", fontWeight: 500 }, labelBgStyle: { fill: "hsl(var(--card))", stroke: "hsl(var(--border))", strokeWidth: 1 }, labelBgPadding: [4, 2] as [number, number], - markerEnd: { type: MarkerType.ArrowClosed, color: "#8b5cf6" }, - style: { stroke: "#8b5cf6", strokeWidth: 2 }, + markerEnd: { type: MarkerType.ArrowClosed, color: "hsl(var(--primary))" }, + style: { stroke: "hsl(var(--primary))", strokeWidth: 2 }, }); } }); @@ -1903,7 +1903,7 @@ function ScreenRelationFlowInner({ screen, selectedGroup, initialFocusedScreenId animated: isConnected, style: { ...edge.style, - stroke: isConnected ? "#8b5cf6" : "#d1d5db", + stroke: isConnected ? "hsl(var(--primary))" : "hsl(var(--border))", strokeWidth: isConnected ? 2 : 1, opacity: isConnected ? 1 : 0.3, }, @@ -1920,7 +1920,7 @@ function ScreenRelationFlowInner({ screen, selectedGroup, initialFocusedScreenId animated: isMyConnection, style: { ...edge.style, - stroke: isMyConnection ? "#3b82f6" : "#d1d5db", + stroke: isMyConnection ? "hsl(var(--primary))" : "hsl(var(--border))", strokeWidth: isMyConnection ? 2 : 1, strokeDasharray: isMyConnection ? undefined : "5,5", opacity: isMyConnection ? 1 : 0.3, @@ -2040,7 +2040,7 @@ function ScreenRelationFlowInner({ screen, selectedGroup, initialFocusedScreenId animated: isConnected, style: { ...edge.style, - stroke: isConnected ? "#8b5cf6" : "#d1d5db", + stroke: isConnected ? "hsl(var(--primary))" : "hsl(var(--border))", strokeWidth: isConnected ? 2 : 1, opacity: isConnected ? 1 : 0.3, }, @@ -2076,7 +2076,7 @@ function ScreenRelationFlowInner({ screen, selectedGroup, initialFocusedScreenId animated: true, style: { ...edge.style, - stroke: "#3b82f6", + stroke: "hsl(var(--primary))", strokeWidth: 2, strokeDasharray: "5,5", opacity: 1, @@ -2095,7 +2095,7 @@ function ScreenRelationFlowInner({ screen, selectedGroup, initialFocusedScreenId animated: isMyConnection, style: { ...edge.style, - stroke: isMyConnection ? "#3b82f6" : "#d1d5db", + stroke: isMyConnection ? "hsl(var(--primary))" : "hsl(var(--border))", strokeWidth: isMyConnection ? 2 : 1, strokeDasharray: isMyConnection ? undefined : "5,5", opacity: isMyConnection ? 1 : 0.3,