refactor: 전체 프론트엔드 하드코딩 색상 → CSS 변수 일괄 치환

447+ 파일, 4500+ 줄 변경:
- gray-* → border/bg-muted/text-foreground/text-muted-foreground
- blue-* → primary/ring
- red-* → destructive
- green-* → emerald (일관성)
- indigo-* → primary
- yellow/orange → amber (통일)
- dark mode 변형도 시맨틱 토큰으로 변환

Made-with: Cursor
This commit is contained in:
DDD1542
2026-03-09 14:31:59 +09:00
parent d967cf0a0d
commit 4f10b5e42d
447 changed files with 4520 additions and 4520 deletions

View File

@@ -3150,38 +3150,38 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
{/* 드래그 핸들 - 컴포넌트 외부 상단 */}
<div
className={cn(
"flex h-4 cursor-move items-center justify-between rounded-t border border-b-0 bg-gray-100 px-1",
isSelectedComp ? "border-primary" : "border-gray-200"
"flex h-4 cursor-move items-center justify-between rounded-t border border-b-0 bg-muted px-1",
isSelectedComp ? "border-primary" : "border-border"
)}
style={{ width: displayWidth }}
onMouseDown={(e) => handlePanelDragStart(e, "left", comp)}
>
<div className="flex items-center gap-0.5">
<Move className="h-2.5 w-2.5 text-gray-400" />
<span className="max-w-[100px] truncate text-[9px] text-gray-500">
<Move className="h-2.5 w-2.5 text-muted-foreground/70" />
<span className="max-w-[100px] truncate text-[9px] text-muted-foreground">
{comp.label || comp.componentType}
</span>
</div>
<div className="flex items-center">
<button
className="rounded p-0.5 hover:bg-gray-200"
className="rounded p-0.5 hover:bg-muted/80"
onClick={(e) => {
e.stopPropagation();
onSelectPanelComponent?.("left", comp.id, comp);
}}
title="설정"
>
<Settings className="h-2.5 w-2.5 text-gray-500" />
<Settings className="h-2.5 w-2.5 text-muted-foreground" />
</button>
<button
className="rounded p-0.5 hover:bg-red-100"
className="rounded p-0.5 hover:bg-destructive/10"
onClick={(e) => {
e.stopPropagation();
handleRemovePanelComponent("left", comp.id);
}}
title="삭제"
>
<Trash2 className="h-2.5 w-2.5 text-red-500" />
<Trash2 className="h-2.5 w-2.5 text-destructive" />
</button>
</div>
</div>
@@ -3192,7 +3192,7 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
"relative overflow-hidden rounded-b border bg-white shadow-sm",
isSelectedComp
? "border-primary ring-2 ring-primary/30"
: "border-gray-200",
: "border-border",
(isDraggingComp || isResizingComp) && "opacity-80 shadow-lg",
!(isDraggingComp || isResizingComp) && "transition-all"
)}
@@ -3270,12 +3270,12 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
)
) : (
// 컴포넌트가 없을 때 드롭 영역 표시
<div className="flex h-full w-full flex-col items-center justify-center rounded border-2 border-dashed border-gray-300 bg-gray-50/50">
<Plus className="mb-2 h-8 w-8 text-gray-400" />
<p className="text-sm font-medium text-gray-500">
<div className="flex h-full w-full flex-col items-center justify-center rounded border-2 border-dashed border-input bg-muted/50">
<Plus className="mb-2 h-8 w-8 text-muted-foreground/70" />
<p className="text-sm font-medium text-muted-foreground">
</p>
<p className="mt-1 text-xs text-gray-400">
<p className="mt-1 text-xs text-muted-foreground/70">
{isDesignMode ? "컴포넌트를 드래그하여 배치하세요" : "배치된 컴포넌트가 없습니다"}
</p>
</div>
@@ -3287,21 +3287,21 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
{isDesignMode ? (
// 디자인 모드: 샘플 테이블
<div className="overflow-auto">
<table className="min-w-full divide-y divide-gray-200">
<thead className="bg-gray-50">
<table className="min-w-full divide-y divide-border">
<thead className="bg-muted">
<tr>
<th className="px-3 py-2 text-left text-xs font-medium text-gray-500 uppercase"> 1</th>
<th className="px-3 py-2 text-left text-xs font-medium text-gray-500 uppercase"> 2</th>
<th className="px-3 py-2 text-left text-xs font-medium text-gray-500 uppercase"> 3</th>
<th className="px-3 py-2 text-left text-xs font-medium text-muted-foreground uppercase"> 1</th>
<th className="px-3 py-2 text-left text-xs font-medium text-muted-foreground uppercase"> 2</th>
<th className="px-3 py-2 text-left text-xs font-medium text-muted-foreground uppercase"> 3</th>
</tr>
</thead>
<tbody className="divide-y divide-gray-200 bg-white">
<tr className="cursor-pointer hover:bg-gray-50">
<tbody className="divide-y divide-border bg-white">
<tr className="cursor-pointer hover:bg-muted">
<td className="px-3 py-2 text-sm whitespace-nowrap"> 1-1</td>
<td className="px-3 py-2 text-sm whitespace-nowrap"> 1-2</td>
<td className="px-3 py-2 text-sm whitespace-nowrap"> 1-3</td>
</tr>
<tr className="cursor-pointer hover:bg-gray-50">
<tr className="cursor-pointer hover:bg-muted">
<td className="px-3 py-2 text-sm whitespace-nowrap"> 2-1</td>
<td className="px-3 py-2 text-sm whitespace-nowrap"> 2-2</td>
<td className="px-3 py-2 text-sm whitespace-nowrap"> 2-3</td>
@@ -3371,16 +3371,16 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
<div className="overflow-auto">
{groupedLeftData.map((group, groupIdx) => (
<div key={groupIdx} className="mb-4">
<div className="bg-gray-100 px-3 py-2 text-sm font-semibold">
<div className="bg-muted px-3 py-2 text-sm font-semibold">
{group.groupKey} ({group.count})
</div>
<table className="min-w-full divide-y divide-gray-200">
<thead className="bg-gray-50">
<table className="min-w-full divide-y divide-border">
<thead className="bg-muted">
<tr>
{columnsToShow.map((col, idx) => (
<th
key={idx}
className="px-3 py-2 text-left text-xs font-medium tracking-wider text-gray-500 uppercase whitespace-nowrap"
className="px-3 py-2 text-left text-xs font-medium tracking-wider text-muted-foreground uppercase whitespace-nowrap"
style={{
width: col.width ? `${col.width}px` : "auto",
minWidth: "80px",
@@ -3391,12 +3391,12 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
</th>
))}
{hasGroupedLeftActions && (
<th className="px-3 py-2 text-right text-xs font-medium tracking-wider text-gray-500 uppercase whitespace-nowrap" style={{ width: "80px" }}>
<th className="px-3 py-2 text-right text-xs font-medium tracking-wider text-muted-foreground uppercase whitespace-nowrap" style={{ width: "80px" }}>
</th>
)}
</tr>
</thead>
<tbody className="divide-y divide-gray-200 bg-white">
<tbody className="divide-y divide-border bg-white">
{group.items.map((item, idx) => {
const sourceColumn = componentConfig.leftPanel?.itemAddConfig?.sourceColumn || "id";
const itemId = item[sourceColumn] || item.id || item.ID || idx;
@@ -3415,7 +3415,7 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
{columnsToShow.map((col, colIdx) => (
<td
key={colIdx}
className="px-3 py-2 text-sm whitespace-nowrap text-gray-900"
className="px-3 py-2 text-sm whitespace-nowrap text-foreground"
style={{ textAlign: col.align || "left" }}
>
{formatCellValue(
@@ -3435,9 +3435,9 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
e.stopPropagation();
handleEditClick("left", item);
}}
className="rounded p-1 transition-colors hover:bg-gray-200"
className="rounded p-1 transition-colors hover:bg-muted/80"
>
<Pencil className="h-3.5 w-3.5 text-gray-500" />
<Pencil className="h-3.5 w-3.5 text-muted-foreground" />
</button>
)}
{(componentConfig.leftPanel?.showDelete !== false) && (
@@ -3446,9 +3446,9 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
e.stopPropagation();
handleDeleteClick("left", item);
}}
className="rounded p-1 transition-colors hover:bg-red-100"
className="rounded p-1 transition-colors hover:bg-destructive/10"
>
<Trash2 className="h-3.5 w-3.5 text-red-500" />
<Trash2 className="h-3.5 w-3.5 text-destructive" />
</button>
)}
</div>
@@ -3472,13 +3472,13 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
);
return (
<div className="overflow-auto">
<table className="min-w-full divide-y divide-gray-200">
<thead className="sticky top-0 z-10 bg-gray-50">
<table className="min-w-full divide-y divide-border">
<thead className="sticky top-0 z-10 bg-muted">
<tr>
{columnsToShow.map((col, idx) => (
<th
key={idx}
className="px-3 py-2 text-left text-xs font-medium tracking-wider text-gray-500 uppercase whitespace-nowrap"
className="px-3 py-2 text-left text-xs font-medium tracking-wider text-muted-foreground uppercase whitespace-nowrap"
style={{
width: col.width ? `${col.width}px` : "auto",
minWidth: "80px",
@@ -3489,12 +3489,12 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
</th>
))}
{hasLeftTableActions && (
<th className="px-3 py-2 text-right text-xs font-medium tracking-wider text-gray-500 uppercase whitespace-nowrap" style={{ width: "80px" }}>
<th className="px-3 py-2 text-right text-xs font-medium tracking-wider text-muted-foreground uppercase whitespace-nowrap" style={{ width: "80px" }}>
</th>
)}
</tr>
</thead>
<tbody className="divide-y divide-gray-200 bg-white">
<tbody className="divide-y divide-border bg-white">
{filteredData.map((item, idx) => {
const sourceColumn = componentConfig.leftPanel?.itemAddConfig?.sourceColumn || "id";
const itemId = item[sourceColumn] || item.id || item.ID || idx;
@@ -3513,7 +3513,7 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
{columnsToShow.map((col, colIdx) => (
<td
key={colIdx}
className="px-3 py-2 text-sm whitespace-nowrap text-gray-900"
className="px-3 py-2 text-sm whitespace-nowrap text-foreground"
style={{ textAlign: col.align || "left" }}
>
{formatCellValue(
@@ -3533,9 +3533,9 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
e.stopPropagation();
handleEditClick("left", item);
}}
className="rounded p-1 transition-colors hover:bg-gray-200"
className="rounded p-1 transition-colors hover:bg-muted/80"
>
<Pencil className="h-3.5 w-3.5 text-gray-500" />
<Pencil className="h-3.5 w-3.5 text-muted-foreground" />
</button>
)}
{(componentConfig.leftPanel?.showDelete !== false) && (
@@ -3544,9 +3544,9 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
e.stopPropagation();
handleDeleteClick("left", item);
}}
className="rounded p-1 transition-colors hover:bg-red-100"
className="rounded p-1 transition-colors hover:bg-destructive/10"
>
<Trash2 className="h-3.5 w-3.5 text-red-500" />
<Trash2 className="h-3.5 w-3.5 text-destructive" />
</button>
)}
</div>
@@ -3699,9 +3699,9 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
{hasChildren ? (
<div className="flex-shrink-0">
{isExpanded ? (
<ChevronDown className="h-4 w-4 text-gray-500" />
<ChevronDown className="h-4 w-4 text-muted-foreground" />
) : (
<ChevronRight className="h-4 w-4 text-gray-500" />
<ChevronRight className="h-4 w-4 text-muted-foreground" />
)}
</div>
) : (
@@ -3726,10 +3726,10 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
e.stopPropagation();
handleEditClick("left", item);
}}
className="rounded p-1 transition-colors hover:bg-gray-200"
className="rounded p-1 transition-colors hover:bg-muted/80"
title="수정"
>
<Pencil className="h-4 w-4 text-gray-600" />
<Pencil className="h-4 w-4 text-muted-foreground" />
</button>
)}
@@ -3740,10 +3740,10 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
e.stopPropagation();
handleDeleteClick("left", item);
}}
className="rounded p-1 transition-colors hover:bg-red-100"
className="rounded p-1 transition-colors hover:bg-destructive/10"
title="삭제"
>
<Trash2 className="h-4 w-4 text-red-600" />
<Trash2 className="h-4 w-4 text-destructive" />
</button>
)}
@@ -3754,10 +3754,10 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
e.stopPropagation();
handleItemAddClick(item);
}}
className="rounded p-1 transition-colors hover:bg-gray-200"
className="rounded p-1 transition-colors hover:bg-muted/80"
title="하위 항목 추가"
>
<Plus className="h-4 w-4 text-gray-600" />
<Plus className="h-4 w-4 text-muted-foreground" />
</button>
)}
</div>
@@ -4272,38 +4272,38 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
>
<div
className={cn(
"flex h-4 cursor-move items-center justify-between rounded-t border border-b-0 bg-gray-100 px-1",
isSelectedComp ? "border-primary" : "border-gray-200"
"flex h-4 cursor-move items-center justify-between rounded-t border border-b-0 bg-muted px-1",
isSelectedComp ? "border-primary" : "border-border"
)}
style={{ width: displayWidth }}
onMouseDown={(e) => handlePanelDragStart(e, "right", comp)}
>
<div className="flex items-center gap-0.5">
<Move className="h-2.5 w-2.5 text-gray-400" />
<span className="max-w-[100px] truncate text-[9px] text-gray-500">
<Move className="h-2.5 w-2.5 text-muted-foreground/70" />
<span className="max-w-[100px] truncate text-[9px] text-muted-foreground">
{comp.label || comp.componentType}
</span>
</div>
<div className="flex items-center">
<button
className="rounded p-0.5 hover:bg-gray-200"
className="rounded p-0.5 hover:bg-muted/80"
onClick={(e) => {
e.stopPropagation();
onSelectPanelComponent?.("right", comp.id, comp);
}}
title="설정"
>
<Settings className="h-2.5 w-2.5 text-gray-500" />
<Settings className="h-2.5 w-2.5 text-muted-foreground" />
</button>
<button
className="rounded p-0.5 hover:bg-red-100"
className="rounded p-0.5 hover:bg-destructive/10"
onClick={(e) => {
e.stopPropagation();
handleRemovePanelComponent("right", comp.id);
}}
title="삭제"
>
<Trash2 className="h-2.5 w-2.5 text-red-500" />
<Trash2 className="h-2.5 w-2.5 text-destructive" />
</button>
</div>
</div>
@@ -4313,7 +4313,7 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
"relative overflow-hidden rounded-b border bg-white shadow-sm",
isSelectedComp
? "border-primary ring-2 ring-primary/30"
: "border-gray-200",
: "border-border",
(isDraggingComp || isResizingComp) && "opacity-80 shadow-lg",
!(isDraggingComp || isResizingComp) && "transition-all"
)}
@@ -4380,12 +4380,12 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
)
) : (
// 컴포넌트가 없을 때 드롭 영역 표시
<div className="flex h-full w-full flex-col items-center justify-center rounded border-2 border-dashed border-gray-300 bg-gray-50/50">
<Plus className="mb-2 h-8 w-8 text-gray-400" />
<p className="text-sm font-medium text-gray-500">
<div className="flex h-full w-full flex-col items-center justify-center rounded border-2 border-dashed border-input bg-muted/50">
<Plus className="mb-2 h-8 w-8 text-muted-foreground/70" />
<p className="text-sm font-medium text-muted-foreground">
</p>
<p className="mt-1 text-xs text-gray-400">
<p className="mt-1 text-xs text-muted-foreground/70">
{isDesignMode ? "컴포넌트를 드래그하여 배치하세요" : "배치된 컴포넌트가 없습니다"}
</p>
</div>
@@ -4550,10 +4550,10 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
e.stopPropagation();
handleDeleteClick("right", item);
}}
className="rounded p-1 transition-colors hover:bg-red-100"
className="rounded p-1 transition-colors hover:bg-destructive/10"
title={componentConfig.rightPanel?.deleteButton?.buttonLabel || "삭제"}
>
<Trash2 className="h-4 w-4 text-red-600" />
<Trash2 className="h-4 w-4 text-destructive" />
</button>
)}
</div>
@@ -4883,7 +4883,7 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
<div key={index}>
<Label htmlFor={col.name} className="text-xs sm:text-sm">
{col.label} {col.required && <span className="text-destructive">*</span>}
{isPreFilled && <span className="ml-2 text-[10px] text-blue-600">( )</span>}
{isPreFilled && <span className="ml-2 text-[10px] text-primary">( )</span>}
</Label>
<Input
id={col.name}