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

@@ -52,14 +52,14 @@ function SortableColumnRow({
className={cn(
"flex items-center gap-1.5 rounded-md border bg-card px-2 py-1.5",
isDragging && "z-50 opacity-50 shadow-md",
isEntityJoin && "border-blue-200 bg-blue-50/30",
isEntityJoin && "border-primary/20 bg-primary/10/30",
)}
>
<div {...attributes} {...listeners} className="text-muted-foreground hover:text-foreground cursor-grab touch-none">
<GripVertical className="h-3 w-3" />
</div>
{isEntityJoin ? (
<Link2 className="h-3 w-3 shrink-0 text-blue-500" title="Entity 조인 컬럼" />
<Link2 className="h-3 w-3 shrink-0 text-primary" title="Entity 조인 컬럼" />
) : (
<span className="text-muted-foreground w-5 shrink-0 text-center text-[10px] font-medium">#{index + 1}</span>
)}
@@ -357,12 +357,12 @@ const AdditionalTabConfigPanel: React.FC<AdditionalTabConfigPanelProps> = ({
>
<AccordionTrigger className="px-3 py-2 hover:no-underline">
<div className="flex flex-1 items-center gap-2">
<GripVertical className="h-4 w-4 text-gray-400" />
<GripVertical className="h-4 w-4 text-muted-foreground/70" />
<span className="text-sm font-medium">
{tab.label || `${tabIndex + 1}`}
</span>
{tab.tableName && (
<span className="text-xs text-gray-500">({tab.tableName})</span>
<span className="text-xs text-muted-foreground">({tab.tableName})</span>
)}
</div>
</AccordionTrigger>
@@ -425,7 +425,7 @@ const AdditionalTabConfigPanel: React.FC<AdditionalTabConfigPanelProps> = ({
)}
/>
{table.displayName || table.tableName}
{table.displayName && <span className="ml-2 text-xs text-gray-500">({table.tableName})</span>}
{table.displayName && <span className="ml-2 text-xs text-muted-foreground">({table.tableName})</span>}
</CommandItem>
))}
</CommandGroup>
@@ -452,13 +452,13 @@ const AdditionalTabConfigPanel: React.FC<AdditionalTabConfigPanelProps> = ({
<SelectItem value="list">
<div className="flex flex-col py-1">
<span className="text-sm font-medium"> (LIST)</span>
<span className="text-xs text-gray-500"> ()</span>
<span className="text-xs text-muted-foreground"> ()</span>
</div>
</SelectItem>
<SelectItem value="table">
<div className="flex flex-col py-1">
<span className="text-sm font-medium"> (TABLE)</span>
<span className="text-xs text-gray-500"> </span>
<span className="text-xs text-muted-foreground"> </span>
</div>
</SelectItem>
</SelectContent>
@@ -467,7 +467,7 @@ const AdditionalTabConfigPanel: React.FC<AdditionalTabConfigPanelProps> = ({
{/* 요약 설정 (목록 모드) */}
{(tab.displayMode || "list") === "list" && (
<div className="space-y-3 rounded-lg border border-gray-200 bg-gray-50 p-3">
<div className="space-y-3 rounded-lg border border-border bg-muted p-3">
<Label className="text-sm font-semibold"> </Label>
<div className="space-y-2">
<Label className="text-xs"> </Label>
@@ -477,12 +477,12 @@ const AdditionalTabConfigPanel: React.FC<AdditionalTabConfigPanelProps> = ({
onChange={(e) => updateTab({ summaryColumnCount: parseInt(e.target.value) || 3 })}
className="bg-white"
/>
<p className="text-xs text-gray-500"> (기본: 3개)</p>
<p className="text-xs text-muted-foreground"> (기본: 3개)</p>
</div>
<div className="flex items-center justify-between space-x-2">
<div className="flex-1">
<Label className="text-xs"> </Label>
<p className="text-xs text-gray-500"> </p>
<p className="text-xs text-muted-foreground"> </p>
</div>
<Checkbox
checked={tab.summaryShowLabel ?? true}
@@ -704,13 +704,13 @@ const AdditionalTabConfigPanel: React.FC<AdditionalTabConfigPanelProps> = ({
return (
<details key={`tab-join-${tableIndex}`} className="group">
<summary className="border-border/60 my-2 flex cursor-pointer list-none items-center gap-2 border-t pt-2 select-none">
<ChevronRight className="h-3 w-3 shrink-0 text-blue-500 transition-transform group-open:rotate-90" />
<Link2 className="h-3 w-3 shrink-0 text-blue-500" />
<span className="text-[10px] font-medium text-blue-600">{joinTable.tableName}</span>
<ChevronRight className="h-3 w-3 shrink-0 text-primary transition-transform group-open:rotate-90" />
<Link2 className="h-3 w-3 shrink-0 text-primary" />
<span className="text-[10px] font-medium text-primary">{joinTable.tableName}</span>
{addedCount > 0 && (
<span className="rounded-full bg-blue-100 px-1.5 text-[9px] font-medium text-blue-600">{addedCount} </span>
<span className="rounded-full bg-primary/10 px-1.5 text-[9px] font-medium text-primary">{addedCount} </span>
)}
<span className="text-[9px] text-gray-400">{joinColumnsToShow.length} </span>
<span className="text-[9px] text-muted-foreground/70">{joinColumnsToShow.length} </span>
</summary>
<div className="space-y-0.5 pt-1">
{joinColumnsToShow.map((column, colIndex) => {
@@ -722,7 +722,7 @@ const AdditionalTabConfigPanel: React.FC<AdditionalTabConfigPanelProps> = ({
return (
<div
key={colIndex}
className="flex cursor-pointer items-center gap-2 rounded px-2 py-1.5 hover:bg-blue-50/60"
className="flex cursor-pointer items-center gap-2 rounded px-2 py-1.5 hover:bg-primary/10/60"
onClick={() => {
updateTab({
columns: [...selectedColumns, {
@@ -741,13 +741,13 @@ const AdditionalTabConfigPanel: React.FC<AdditionalTabConfigPanelProps> = ({
}}
>
<Checkbox checked={false} className="pointer-events-none h-3.5 w-3.5 shrink-0" />
<Link2 className="h-3 w-3 shrink-0 text-blue-500" />
<span className="truncate text-xs text-blue-700">{column.columnLabel || column.columnName}</span>
<Link2 className="h-3 w-3 shrink-0 text-primary" />
<span className="truncate text-xs text-primary">{column.columnLabel || column.columnName}</span>
</div>
);
})}
{joinColumnsToShow.length === 0 && (
<p className="px-2 py-1 text-[10px] text-gray-400"> </p>
<p className="px-2 py-1 text-[10px] text-muted-foreground/70"> </p>
)}
</div>
</details>
@@ -784,8 +784,8 @@ const AdditionalTabConfigPanel: React.FC<AdditionalTabConfigPanelProps> = ({
<div className="space-y-2">
{(tab.addModalColumns || []).length === 0 ? (
<div className="rounded-md border border-dashed border-gray-300 bg-white p-3 text-center">
<p className="text-xs text-gray-500"> </p>
<div className="rounded-md border border-dashed border-input bg-white p-3 text-center">
<p className="text-xs text-muted-foreground"> </p>
</div>
) : (
(tab.addModalColumns || []).map((col, colIndex) => (
@@ -842,7 +842,7 @@ const AdditionalTabConfigPanel: React.FC<AdditionalTabConfigPanelProps> = ({
const newColumns = (tab.addModalColumns || []).filter((_, i) => i !== colIndex);
updateTab({ addModalColumns: newColumns });
}}
className="h-8 w-8 p-0 text-red-500"
className="h-8 w-8 p-0 text-destructive"
>
<X className="h-3 w-3" />
</Button>
@@ -1038,7 +1038,7 @@ const AdditionalTabConfigPanel: React.FC<AdditionalTabConfigPanelProps> = ({
{/* 그룹핑 기준 컬럼 */}
<div className="space-y-1">
<Label className="text-[10px]"> </Label>
<p className="text-[9px] text-gray-500"> </p>
<p className="text-[9px] text-muted-foreground"> </p>
<div className="max-h-[120px] space-y-1 overflow-y-auto rounded-md border bg-white p-2">
{tabColumns.map((col) => (
<div key={col.columnName} className="flex items-center gap-2">
@@ -1185,7 +1185,7 @@ const AdditionalTabConfigPanel: React.FC<AdditionalTabConfigPanelProps> = ({
<Button
variant="ghost"
size="sm"
className="text-red-500 hover:bg-red-50 hover:text-red-600"
className="text-destructive hover:bg-destructive/10 hover:text-destructive"
onClick={() => {
const newTabs = config.rightPanel?.additionalTabs?.filter((_, i) => i !== tabIndex) || [];
updateRightPanel({ additionalTabs: newTabs });
@@ -1557,7 +1557,7 @@ export const SplitPanelLayoutConfigPanel: React.FC<SplitPanelLayoutConfigPanelPr
return (
<div className="rounded-lg border p-4">
<p className="text-sm font-medium"> .</p>
<p className="mt-1 text-xs text-gray-600">
<p className="mt-1 text-xs text-muted-foreground">
.
</p>
</div>
@@ -1649,13 +1649,13 @@ export const SplitPanelLayoutConfigPanel: React.FC<SplitPanelLayoutConfigPanelPr
<SelectItem value="detail">
<div className="flex flex-col py-1">
<span className="text-sm font-medium"> </span>
<span className="text-xs text-gray-500"> / </span>
<span className="text-xs text-muted-foreground"> / </span>
</div>
</SelectItem>
<SelectItem value="join">
<div className="flex flex-col py-1">
<span className="text-sm font-medium"> </span>
<span className="text-xs text-gray-500"> / </span>
<span className="text-xs text-muted-foreground"> / </span>
</div>
</SelectItem>
</SelectContent>
@@ -1755,7 +1755,7 @@ export const SplitPanelLayoutConfigPanel: React.FC<SplitPanelLayoutConfigPanelPr
config.leftPanel?.tableName === screenTableName ? "opacity-100" : "opacity-0"
)}
/>
<Database className="mr-2 h-3.5 w-3.5 text-blue-500" />
<Database className="mr-2 h-3.5 w-3.5 text-primary" />
{allTables.find((t) => (t.tableName || t.table_name) === screenTableName)?.tableLabel ||
allTables.find((t) => (t.tableName || t.table_name) === screenTableName)?.displayName ||
screenTableName}
@@ -1848,19 +1848,19 @@ export const SplitPanelLayoutConfigPanel: React.FC<SplitPanelLayoutConfigPanelPr
<SelectItem value="list">
<div className="flex flex-col py-1">
<span className="text-sm font-medium"> (LIST)</span>
<span className="text-xs text-gray-500"> ()</span>
<span className="text-xs text-muted-foreground"> ()</span>
</div>
</SelectItem>
<SelectItem value="table">
<div className="flex flex-col py-1">
<span className="text-sm font-medium"> (TABLE)</span>
<span className="text-xs text-gray-500"> </span>
<span className="text-xs text-muted-foreground"> </span>
</div>
</SelectItem>
<SelectItem value="custom">
<div className="flex flex-col py-1">
<span className="text-sm font-medium"> (CUSTOM)</span>
<span className="text-xs text-gray-500"> </span>
<span className="text-xs text-muted-foreground"> </span>
</div>
</SelectItem>
</SelectContent>
@@ -2039,13 +2039,13 @@ export const SplitPanelLayoutConfigPanel: React.FC<SplitPanelLayoutConfigPanelPr
return (
<details key={`join-${tableIndex}`} className="group">
<summary className="border-border/60 my-2 flex cursor-pointer list-none items-center gap-2 border-t pt-2 select-none">
<ChevronRight className="h-3 w-3 shrink-0 text-blue-500 transition-transform group-open:rotate-90" />
<Link2 className="h-3 w-3 shrink-0 text-blue-500" />
<span className="text-[10px] font-medium text-blue-600">{joinTable.tableName}</span>
<ChevronRight className="h-3 w-3 shrink-0 text-primary transition-transform group-open:rotate-90" />
<Link2 className="h-3 w-3 shrink-0 text-primary" />
<span className="text-[10px] font-medium text-primary">{joinTable.tableName}</span>
{addedCount > 0 && (
<span className="rounded-full bg-blue-100 px-1.5 text-[9px] font-medium text-blue-600">{addedCount} </span>
<span className="rounded-full bg-primary/10 px-1.5 text-[9px] font-medium text-primary">{addedCount} </span>
)}
<span className="text-[9px] text-gray-400">{joinColumnsToShow.length} </span>
<span className="text-[9px] text-muted-foreground/70">{joinColumnsToShow.length} </span>
</summary>
<div className="space-y-0.5 pt-1">
{joinColumnsToShow.map((column, colIndex) => {
@@ -2057,7 +2057,7 @@ export const SplitPanelLayoutConfigPanel: React.FC<SplitPanelLayoutConfigPanelPr
return (
<div
key={colIndex}
className="flex cursor-pointer items-center gap-2 rounded px-2 py-1.5 hover:bg-blue-50/60"
className="flex cursor-pointer items-center gap-2 rounded px-2 py-1.5 hover:bg-primary/10/60"
onClick={() => {
updateLeftPanel({
columns: [...selectedColumns, {
@@ -2076,13 +2076,13 @@ export const SplitPanelLayoutConfigPanel: React.FC<SplitPanelLayoutConfigPanelPr
}}
>
<Checkbox checked={false} className="pointer-events-none h-3.5 w-3.5 shrink-0" />
<Link2 className="h-3 w-3 shrink-0 text-blue-500" />
<span className="truncate text-xs text-blue-700">{column.columnLabel || column.columnName}</span>
<Link2 className="h-3 w-3 shrink-0 text-primary" />
<span className="truncate text-xs text-primary">{column.columnLabel || column.columnName}</span>
</div>
);
})}
{joinColumnsToShow.length === 0 && (
<p className="px-2 py-1 text-[10px] text-gray-400"> </p>
<p className="px-2 py-1 text-[10px] text-muted-foreground/70"> </p>
)}
</div>
</details>
@@ -2362,7 +2362,7 @@ export const SplitPanelLayoutConfigPanel: React.FC<SplitPanelLayoutConfigPanelPr
)}
/>
{table.displayName || table.tableName}
{table.displayName && <span className="ml-2 text-xs text-gray-500">({table.tableName})</span>}
{table.displayName && <span className="ml-2 text-xs text-muted-foreground">({table.tableName})</span>}
</CommandItem>
))}
</CommandGroup>
@@ -2386,19 +2386,19 @@ export const SplitPanelLayoutConfigPanel: React.FC<SplitPanelLayoutConfigPanelPr
<SelectItem value="list">
<div className="flex flex-col py-1">
<span className="text-sm font-medium"> (LIST)</span>
<span className="text-xs text-gray-500"> ()</span>
<span className="text-xs text-muted-foreground"> ()</span>
</div>
</SelectItem>
<SelectItem value="table">
<div className="flex flex-col py-1">
<span className="text-sm font-medium"> (TABLE)</span>
<span className="text-xs text-gray-500"> </span>
<span className="text-xs text-muted-foreground"> </span>
</div>
</SelectItem>
<SelectItem value="custom">
<div className="flex flex-col py-1">
<span className="text-sm font-medium"> (CUSTOM)</span>
<span className="text-xs text-gray-500"> </span>
<span className="text-xs text-muted-foreground"> </span>
</div>
</SelectItem>
</SelectContent>
@@ -2464,7 +2464,7 @@ export const SplitPanelLayoutConfigPanel: React.FC<SplitPanelLayoutConfigPanelPr
{/* 요약 표시 설정 (LIST 모드에서만, 커스텀 모드가 아닐 때) */}
{(config.rightPanel?.displayMode || "list") === "list" && (
<div className="space-y-3 rounded-lg border border-gray-200 bg-gray-50 p-3">
<div className="space-y-3 rounded-lg border border-border bg-muted p-3">
<Label className="text-sm font-semibold"> </Label>
<div className="space-y-2">
@@ -2480,13 +2480,13 @@ export const SplitPanelLayoutConfigPanel: React.FC<SplitPanelLayoutConfigPanelPr
}}
className="bg-white"
/>
<p className="text-xs text-gray-500"> (기본: 3개)</p>
<p className="text-xs text-muted-foreground"> (기본: 3개)</p>
</div>
<div className="flex items-center justify-between space-x-2">
<div className="flex-1">
<Label className="text-xs"> </Label>
<p className="text-xs text-gray-500"> </p>
<p className="text-xs text-muted-foreground"> </p>
</div>
<Checkbox
checked={config.rightPanel?.summaryShowLabel ?? true}
@@ -2622,13 +2622,13 @@ export const SplitPanelLayoutConfigPanel: React.FC<SplitPanelLayoutConfigPanelPr
return (
<details key={`join-${tableIndex}`} className="group">
<summary className="border-border/60 my-2 flex cursor-pointer list-none items-center gap-2 border-t pt-2 select-none">
<ChevronRight className="h-3 w-3 shrink-0 text-blue-500 transition-transform group-open:rotate-90" />
<Link2 className="h-3 w-3 shrink-0 text-blue-500" />
<span className="text-[10px] font-medium text-blue-600">{joinTable.tableName}</span>
<ChevronRight className="h-3 w-3 shrink-0 text-primary transition-transform group-open:rotate-90" />
<Link2 className="h-3 w-3 shrink-0 text-primary" />
<span className="text-[10px] font-medium text-primary">{joinTable.tableName}</span>
{addedCount > 0 && (
<span className="rounded-full bg-blue-100 px-1.5 text-[9px] font-medium text-blue-600">{addedCount} </span>
<span className="rounded-full bg-primary/10 px-1.5 text-[9px] font-medium text-primary">{addedCount} </span>
)}
<span className="text-[9px] text-gray-400">{joinColumnsToShow.length} </span>
<span className="text-[9px] text-muted-foreground/70">{joinColumnsToShow.length} </span>
</summary>
<div className="space-y-0.5 pt-1">
{joinColumnsToShow.map((column, colIndex) => {
@@ -2640,7 +2640,7 @@ export const SplitPanelLayoutConfigPanel: React.FC<SplitPanelLayoutConfigPanelPr
return (
<div
key={colIndex}
className="flex cursor-pointer items-center gap-2 rounded px-2 py-1.5 hover:bg-blue-50/60"
className="flex cursor-pointer items-center gap-2 rounded px-2 py-1.5 hover:bg-primary/10/60"
onClick={() => {
updateRightPanel({
columns: [...selectedColumns, {
@@ -2659,13 +2659,13 @@ export const SplitPanelLayoutConfigPanel: React.FC<SplitPanelLayoutConfigPanelPr
}}
>
<Checkbox checked={false} className="pointer-events-none h-3.5 w-3.5 shrink-0" />
<Link2 className="h-3 w-3 shrink-0 text-blue-500" />
<span className="truncate text-xs text-blue-700">{column.columnLabel || column.columnName}</span>
<Link2 className="h-3 w-3 shrink-0 text-primary" />
<span className="truncate text-xs text-primary">{column.columnLabel || column.columnName}</span>
</div>
);
})}
{joinColumnsToShow.length === 0 && (
<p className="px-2 py-1 text-[10px] text-gray-400"> </p>
<p className="px-2 py-1 text-[10px] text-muted-foreground/70"> </p>
)}
</div>
</details>
@@ -3209,7 +3209,7 @@ export const SplitPanelLayoutConfigPanel: React.FC<SplitPanelLayoutConfigPanelPr
</Accordion>
) : (
<div className="rounded-lg border border-dashed p-4 text-center">
<p className="text-xs text-gray-500">
<p className="text-xs text-muted-foreground">
. [ ] .
</p>
</div>