wing-ops/frontend/src/pages/design/designTheme.ts
leedano d0491c3f0f feat(design): Stitch MCP 기반 디자인 시스템 카탈로그 + SCAT 하드코딩 해안선 제거
- react-router-dom 도입, /design 경로에 디자인 토큰/컴포넌트 카탈로그 페이지 추가
- SCAT 지도에서 하드코딩된 제주 해안선 좌표 제거, 인접 구간 기반 동적 방향 계산으로 전환
- @/ path alias 추가, SVG 아이콘 에셋 추가
2026-03-24 16:36:50 +09:00

381 lines
12 KiB
TypeScript

// designTheme.ts — 디자인 시스템 페이지 다크/라이트 테마 정의
export type ThemeMode = 'dark' | 'light';
// ---------- 토큰 인터페이스 ----------
export interface BgToken {
bg: string;
token: string;
hex: string;
desc: string;
isHover?: boolean;
}
export interface AccentToken {
color: string;
name: string;
token: string;
badge: string;
glow: string;
badgeBg: string;
badgeBorder: string;
badgeText: string;
}
export interface StatusToken {
color: string;
bg: string;
border: string;
label: string;
hex: string;
glow?: string;
}
export interface BorderToken {
token: string;
hex: string;
border: string;
barBg: string;
}
export interface TextTokenItem {
token: string;
sampleText: string;
sampleClass: string;
desc: string;
descColor: string;
}
// ---------- 테마 인터페이스 ----------
export interface DesignTheme {
mode: ThemeMode;
// 레이아웃
pageBg: string;
sidebarBg: string;
sidebarBorder: string;
sidebarShadow: string;
headerBg: string;
headerBorder: string;
// 텍스트
textPrimary: string;
textSecondary: string;
textMuted: string;
textAccent: string;
// 카드
cardBg: string;
cardBorder: string;
cardBorderHover: string;
cardShadow: string;
// 섹션
sectionTitle: string;
sectionSub: string;
sectionSubSpacing: string;
// 테이블
tableContainerBg: string;
tableHeaderBg: string;
tableRowBorder: string;
tableDataRowBg: string;
// 뱃지
badgeRadius: string;
statusBadgeBg: string;
statusBadgeBorder: string;
statusBadgeDot: string;
statusBadgeText: string;
systemActiveBg: string;
systemActiveBorder: string;
systemActiveShadow: string;
// 폰트 뱃지 (06 타이포그래피)
fontBadgePrimaryBg: string;
fontBadgePrimaryText: string;
fontBadgeSecondaryBorder: string;
fontBadgeSecondaryText: string;
// 타이포 샘플 텍스트
typoSampleText: string;
typoSizeText: string;
typoPropertiesText: string;
typoActionBg: string;
typoActionBorder: string;
typoActionText: string;
typoDataText: string;
typoCoordText: string;
// 02 테두리 색상
borderCardBg: string;
borderCardShadow: string;
// 03 텍스트 색상
textSectionBg: string;
textSectionBorder: string;
// 07 radius
radiusSmLabel: string;
radiusMdLabel: string;
radiusCardBg: string;
radiusCardBorder: string;
radiusCardShadow: string;
radiusDescText: string;
// 푸터
footerBorder: string;
footerText: string;
footerAccent: string;
// 01 배경색 카드 스와치 border
swatchBorder: string;
swatchBorderHover: string;
// 데이터 토큰
bgTokens: BgToken[];
accentTokens: AccentToken[];
statusTokens: StatusToken[];
borderTokens: BorderToken[];
textTokens: TextTokenItem[];
}
// ---------- DARK 테마 ----------
export const DARK_THEME: DesignTheme = {
mode: 'dark',
pageBg: '#0a0e1a',
sidebarBg: '#171b28',
sidebarBorder: 'rgba(255,255,255,0.05)',
sidebarShadow: 'rgba(0,0,0,0.4)',
headerBg: '#0a0e1a',
headerBorder: 'rgba(255,255,255,0.05)',
textPrimary: '#dfe2f3',
textSecondary: '#c2c6d6',
textMuted: '#8c909f',
textAccent: '#4cd7f6',
cardBg: '#171b28',
cardBorder: 'rgba(66,71,84,0.10)',
cardBorderHover: 'rgba(66,71,84,0.20)',
cardShadow: 'none',
sectionTitle: '#adc6ff',
sectionSub: '#8c909f',
sectionSubSpacing: '1px',
tableContainerBg: '#171b28',
tableHeaderBg: '#1b1f2c',
tableRowBorder: 'rgba(66,71,84,0.10)',
tableDataRowBg: 'rgba(10,14,26,0.50)',
badgeRadius: 'rounded-xl',
statusBadgeBg: 'transparent',
statusBadgeBorder: 'transparent',
statusBadgeDot: 'transparent',
statusBadgeText: 'transparent',
systemActiveBg: '#171b28',
systemActiveBorder: 'rgba(66,71,84,0.10)',
systemActiveShadow: '0px 0px 8px 0px rgba(76, 215, 246, 0.5)',
fontBadgePrimaryBg: '#edf0f7',
fontBadgePrimaryText: '#0a0e1a',
fontBadgeSecondaryBorder: 'rgba(66,71,84,0.30)',
fontBadgeSecondaryText: '#8c909f',
typoSampleText: '#c2c6d6',
typoSizeText: '#8c909f',
typoPropertiesText: '#c2c6d6',
typoActionBg: 'rgba(76,215,246,0.10)',
typoActionBorder: 'rgba(76,215,246,0.20)',
typoActionText: '#4cd7f6',
typoDataText: '#4cd7f6',
typoCoordText: '#8c909f',
borderCardBg: 'rgba(15,21,36,0.50)',
borderCardShadow: 'none',
textSectionBg: '#0a0e1a',
textSectionBorder: 'rgba(66,71,84,0.10)',
radiusSmLabel: 'radius-sm (6px)',
radiusMdLabel: 'radius-md (10px)',
radiusCardBg: '#171b28',
radiusCardBorder: 'rgba(66,71,84,0.20)',
radiusCardShadow: 'none',
radiusDescText: '#c2c6d6',
footerBorder: 'rgba(66,71,84,0.10)',
footerText: '#8c909f',
footerAccent: '#4cd7f6',
swatchBorder: 'rgba(255,255,255,0.05)',
swatchBorderHover: 'rgba(76,215,246,0.20)',
bgTokens: [
{ bg: '#0a0e1a', token: 'bg-0', hex: '#0a0e1a', desc: 'Primary page canvas, deepest immersion layer.' },
{ bg: '#0f1524', token: 'bg-1', hex: '#0f1524', desc: 'Surface Level 1: Sidebar containers and utility panels.' },
{ bg: '#121929', token: 'bg-2', hex: '#121929', desc: 'Surface Level 2: Table headers and subtle sectional shifts.' },
{ bg: '#1a2236', token: 'bg-3', hex: '#1a2236', desc: 'Surface Level 3: Elevated cards and floating elements.' },
{ bg: '#1e2844', token: 'bg-hover', hex: '#1e2844', desc: 'Interactive states, list item highlighting.', isHover: true },
],
accentTokens: [
{
color: '#06b6d4', name: 'Cyan Accent', token: 'primary', badge: 'Primary Action',
glow: '0px 0px 15px 0px rgba(6,182,212,0.4)',
badgeBg: 'rgba(6,182,212,0.10)', badgeBorder: 'rgba(6,182,212,0.25)', badgeText: '#06b6d4',
},
{
color: '#3b82f6', name: 'Blue Accent', token: 'secondary', badge: 'Information',
glow: '0px 0px 15px 0px rgba(59,130,246,0.3)',
badgeBg: 'rgba(59,130,246,0.10)', badgeBorder: 'rgba(59,130,246,0.25)', badgeText: '#3b82f6',
},
{
color: '#a855f7', name: 'Purple Accent', token: 'tertiary', badge: 'Operations',
glow: '0px 0px 15px 0px rgba(168,85,247,0.3)',
badgeBg: 'rgba(168,85,247,0.10)', badgeBorder: 'rgba(168,85,247,0.25)', badgeText: '#a855f7',
},
],
statusTokens: [
{ color: '#ef4444', bg: 'rgba(239,68,68,0.05)', border: 'rgba(239,68,68,0.20)', label: '위험 Critical', hex: '#ef4444', glow: '0px 0px 8px 0px rgba(239, 68, 68, 0.6)' },
{ color: '#f97316', bg: 'rgba(249,115,22,0.05)', border: 'rgba(249,115,22,0.20)', label: '주의 Warning', hex: '#f97316' },
{ color: '#eab308', bg: 'rgba(234,179,8,0.05)', border: 'rgba(234,179,8,0.20)', label: '경고 Caution', hex: '#eab308' },
{ color: '#22c55e', bg: 'rgba(34,197,94,0.05)', border: 'rgba(34,197,94,0.20)', label: '정상 Normal', hex: '#22c55e' },
],
borderTokens: [
{ token: 'border', hex: '#1e2a42', border: '#1e2a42', barBg: '#1e2a42' },
{ token: 'border-light', hex: '#2a3a5c', border: '#2a3a5c', barBg: '#2a3a5c' },
],
textTokens: [
{ token: 'text-1', sampleText: '주요 텍스트 Primary Text', sampleClass: 'text-[#edf0f7] font-korean text-[15px] font-bold', desc: 'Headings, active values, and primary labels.', descColor: 'rgba(237,240,247,0.60)' },
{ token: 'text-2', sampleText: '보조 텍스트 Secondary Text', sampleClass: 'text-[#b0b8cc] font-korean text-[15px] font-medium', desc: 'Supporting labels and secondary information.', descColor: 'rgba(176,184,204,0.60)' },
{ token: 'text-3', sampleText: '비활성 텍스트 Muted Text', sampleClass: 'text-[#8690a6] font-korean text-[15px]', desc: 'Disabled states, placeholders, and captions.', descColor: 'rgba(134,144,166,0.60)' },
],
};
// ---------- LIGHT 테마 ----------
export const LIGHT_THEME: DesignTheme = {
mode: 'light',
pageBg: '#f8fafc',
sidebarBg: '#ffffff',
sidebarBorder: '#e2e8f0',
sidebarShadow: 'rgba(0,0,0,0.05)',
headerBg: '#ffffff',
headerBorder: '#e2e8f0',
textPrimary: '#0f172a',
textSecondary: '#64748b',
textMuted: '#94a3b8',
textAccent: '#06b6d4',
cardBg: '#ffffff',
cardBorder: '#e2e8f0',
cardBorderHover: 'rgba(6,182,212,0.20)',
cardShadow: '0px 1px 2px 0px rgba(0,0,0,0.05)',
sectionTitle: '#1e293b',
sectionSub: '#94a3b8',
sectionSubSpacing: '-0.5px',
tableContainerBg: '#ffffff',
tableHeaderBg: '#f8fafc',
tableRowBorder: '#f1f5f9',
tableDataRowBg: 'rgba(248,250,252,0.50)',
badgeRadius: 'rounded-full',
statusBadgeBg: 'transparent',
statusBadgeBorder: 'transparent',
statusBadgeDot: 'transparent',
statusBadgeText: 'transparent',
systemActiveBg: '#ffffff',
systemActiveBorder: '#e2e8f0',
systemActiveShadow: '0px 1px 2px 0px rgba(0,0,0,0.05)',
fontBadgePrimaryBg: '#0f172a',
fontBadgePrimaryText: '#ffffff',
fontBadgeSecondaryBorder: '#cbd5e1',
fontBadgeSecondaryText: '#64748b',
typoSampleText: '#64748b',
typoSizeText: '#0f172a',
typoPropertiesText: '#94a3b8',
typoActionBg: 'rgba(6,182,212,0.10)',
typoActionBorder: 'rgba(6,182,212,0.20)',
typoActionText: '#06b6d4',
typoDataText: '#06b6d4',
typoCoordText: '#94a3b8',
borderCardBg: '#ffffff',
borderCardShadow: '0px 1px 2px 0px rgba(0,0,0,0.05)',
textSectionBg: '#ffffff',
textSectionBorder: '#e2e8f0',
radiusSmLabel: 'radius-sm (4px)',
radiusMdLabel: 'radius-md (8px)',
radiusCardBg: '#ffffff',
radiusCardBorder: '#e2e8f0',
radiusCardShadow: '0px 1px 2px 0px rgba(0,0,0,0.05)',
radiusDescText: '#475569',
footerBorder: '#e2e8f0',
footerText: '#94a3b8',
footerAccent: '#06b6d4',
swatchBorder: '#e2e8f0',
swatchBorderHover: 'rgba(6,182,212,0.20)',
bgTokens: [
{ bg: '#f8fafc', token: 'bg-0', hex: '#f8fafc', desc: 'Primary page canvas, lightest foundation layer.' },
{ bg: '#ffffff', token: 'bg-1', hex: '#ffffff', desc: 'Surface Level 1: Sidebar containers and utility panels.' },
{ bg: '#f1f5f9', token: 'bg-2', hex: '#f1f5f9', desc: 'Surface Level 2: Table headers and subtle sectional shifts.' },
{ bg: '#e2e8f0', token: 'bg-3', hex: '#e2e8f0', desc: 'Surface Level 3: Elevated cards and floating elements.' },
{ bg: '#cbd5e1', token: 'bg-hover', hex: '#cbd5e1', desc: 'Interactive states, list item highlighting.', isHover: true },
],
accentTokens: [
{
color: '#06b6d4', name: 'Cyan Accent', token: 'primary', badge: 'Primary Action',
glow: '0px 1px 2px 0px rgba(0,0,0,0.05)',
badgeBg: 'rgba(6,182,212,0.10)', badgeBorder: 'rgba(6,182,212,0.25)', badgeText: '#06b6d4',
},
{
color: '#0891b2', name: 'Teal Accent', token: 'secondary', badge: 'Information',
glow: '0px 1px 2px 0px rgba(0,0,0,0.05)',
badgeBg: 'rgba(8,145,178,0.10)', badgeBorder: 'rgba(8,145,178,0.25)', badgeText: '#0891b2',
},
{
color: '#6366f1', name: 'Indigo Accent', token: 'tertiary', badge: 'Operations',
glow: '0px 1px 2px 0px rgba(0,0,0,0.05)',
badgeBg: 'rgba(99,102,241,0.10)', badgeBorder: 'rgba(99,102,241,0.25)', badgeText: '#6366f1',
},
],
statusTokens: [
{ color: '#dc2626', bg: '#fef2f2', border: '#fecaca', label: '위험 Critical', hex: '#f87171' },
{ color: '#c2410c', bg: '#fff7ed', border: '#fed7aa', label: '주의 Warning', hex: '#fb923c' },
{ color: '#b45309', bg: '#fffbeb', border: '#fde68a', label: '경고 Caution', hex: '#fbbf24' },
{ color: '#047857', bg: '#ecfdf5', border: '#a7f3d0', label: '정상 Normal', hex: '#34d399' },
],
borderTokens: [
{ token: 'border', hex: '#cbd5e1', border: '#cbd5e1', barBg: '#cbd5e1' },
{ token: 'border-light', hex: '#e2e8f0', border: '#e2e8f0', barBg: '#e2e8f0' },
],
textTokens: [
{ token: 'text-1', sampleText: '주요 텍스트 Primary Text', sampleClass: 'text-[#0f172a] font-korean text-[15px] font-bold', desc: 'Headings, active values, and primary labels.', descColor: '#64748b' },
{ token: 'text-2', sampleText: '보조 텍스트 Secondary Text', sampleClass: 'text-[#475569] font-korean text-[15px] font-medium', desc: 'Supporting labels and secondary information.', descColor: '#64748b' },
{ token: 'text-3', sampleText: '비활성 텍스트 Muted Text', sampleClass: 'text-[#94a3b8] font-korean text-[15px]', desc: 'Disabled states, placeholders, and captions.', descColor: '#94a3b8' },
],
};
export const getTheme = (mode: ThemeMode): DesignTheme =>
mode === 'dark' ? DARK_THEME : LIGHT_THEME;