diff --git a/frontend/src/design-system/sections/CatalogSection.tsx b/frontend/src/design-system/sections/CatalogSection.tsx index b055dfc..7400088 100644 --- a/frontend/src/design-system/sections/CatalogSection.tsx +++ b/frontend/src/design-system/sections/CatalogSection.tsx @@ -70,7 +70,10 @@ function CatalogBadges({ catalog, idPrefix }: { catalog: AnyCatalog; idPrefix: s ) : ( {label} diff --git a/frontend/src/lib/theme/variants.ts b/frontend/src/lib/theme/variants.ts index 447fd17..30a249d 100644 --- a/frontend/src/lib/theme/variants.ts +++ b/frontend/src/lib/theme/variants.ts @@ -19,29 +19,34 @@ export const cardVariants = cva('rounded-xl border border-border', { /** 뱃지 변형 — 위험도/상태별 150회+ 반복 패턴 통합 * - * 가독성 정책: - * - 배경: 색상별 진한 솔리드(-400) — 명확한 분류 식별 - * - 텍스트: 시맨틱 토큰 text-on-bright (theme.css = #0f172a) — 테마 무관 일관 가독성 - * - 보더: 같은 색상 계열 -600 (배경 강조) + * 가독성 정책 (테마별 팔레트 분리): + * - **다크 모드**: 솔리드 밝은 배경(-400) + 진한 글자(slate-900) + 강한 보더(-600) + * → 어두운 페이지에서 밝게 튀어 명확한 분류 식별 + * - **라이트 모드**: 파스텔 배경(-100) + 진한 글자(-900) + 부드러운 보더(-300) + * → 흰 배경에 어울리는 소프트 토큰, 글자와 배경 대비 충분 * - 가운데 정렬 - * - 폰트 크기: rem 기반 (root font-size 대비 비율) — 화면 비율에 따라 자동 조정 + * - 폰트 크기: rem 기반 — 화면 비율 대비 자동 조정 * - * className override는 cn(tailwind-merge) 덕분에 같은 그룹(text-color/font-size/bg) 충돌 시 - * 마지막 명시값이 적용 — !important 없이 의도된 override만 허용. + * className override는 cn(tailwind-merge) 덕분에 같은 그룹 충돌 시 마지막 명시값 적용. */ export const badgeVariants = cva( - 'inline-flex items-center justify-center whitespace-nowrap rounded-md border px-2 py-0.5 font-semibold transition-colors text-center text-on-bright', + 'inline-flex items-center justify-center whitespace-nowrap rounded-md border px-2 py-0.5 font-semibold transition-colors text-center', { variants: { intent: { - critical: 'bg-red-400 border-red-600', - high: 'bg-orange-400 border-orange-600', - warning: 'bg-yellow-400 border-yellow-600', - info: 'bg-blue-400 border-blue-600', - success: 'bg-green-400 border-green-600', - muted: 'bg-slate-400 border-slate-600', - purple: 'bg-purple-400 border-purple-600', - cyan: 'bg-cyan-400 border-cyan-600', + critical: + 'bg-red-100 text-red-900 border-red-300 dark:bg-red-400 dark:text-slate-900 dark:border-red-600', + high: 'bg-orange-100 text-orange-900 border-orange-300 dark:bg-orange-400 dark:text-slate-900 dark:border-orange-600', + warning: + 'bg-yellow-100 text-yellow-900 border-yellow-300 dark:bg-yellow-400 dark:text-slate-900 dark:border-yellow-600', + info: 'bg-blue-100 text-blue-900 border-blue-300 dark:bg-blue-400 dark:text-slate-900 dark:border-blue-600', + success: + 'bg-green-100 text-green-900 border-green-300 dark:bg-green-400 dark:text-slate-900 dark:border-green-600', + muted: + 'bg-slate-100 text-slate-800 border-slate-300 dark:bg-slate-400 dark:text-slate-900 dark:border-slate-600', + purple: + 'bg-purple-100 text-purple-900 border-purple-300 dark:bg-purple-400 dark:text-slate-900 dark:border-purple-600', + cyan: 'bg-cyan-100 text-cyan-900 border-cyan-300 dark:bg-cyan-400 dark:text-slate-900 dark:border-cyan-600', }, // rem 기반 — root font-size 대비 비율, 화면 비율 변경 시 자동 조정 // xs ≈ 11px, sm ≈ 12px, md ≈ 13px, lg ≈ 14px (root 14px 기준) diff --git a/frontend/src/shared/constants/enforcementActions.ts b/frontend/src/shared/constants/enforcementActions.ts index a95b107..e9249af 100644 --- a/frontend/src/shared/constants/enforcementActions.ts +++ b/frontend/src/shared/constants/enforcementActions.ts @@ -19,6 +19,7 @@ export interface EnforcementActionMeta { code: EnforcementAction; i18nKey: string; fallback: { ko: string; en: string }; + classes: string; hex: string; order: number; } @@ -28,6 +29,7 @@ export const ENFORCEMENT_ACTIONS: Record = { code: 'NEW', i18nKey: 'eventStatus.NEW', fallback: { ko: '신규', en: 'New' }, - classes: 'bg-red-500/20 text-red-400', + classes: 'bg-red-100 text-red-800 dark:bg-red-500/20 dark:text-red-400', order: 1, }, ACK: { code: 'ACK', i18nKey: 'eventStatus.ACK', fallback: { ko: '확인', en: 'Acknowledged' }, - classes: 'bg-orange-500/20 text-orange-400', + classes: 'bg-orange-100 text-orange-800 dark:bg-orange-500/20 dark:text-orange-400', order: 2, }, IN_PROGRESS: { code: 'IN_PROGRESS', i18nKey: 'eventStatus.IN_PROGRESS', fallback: { ko: '처리중', en: 'In Progress' }, - classes: 'bg-blue-500/20 text-blue-400', + classes: 'bg-blue-100 text-blue-800 dark:bg-blue-500/20 dark:text-blue-400', order: 3, }, RESOLVED: { code: 'RESOLVED', i18nKey: 'eventStatus.RESOLVED', fallback: { ko: '완료', en: 'Resolved' }, - classes: 'bg-green-500/20 text-green-400', + classes: 'bg-green-100 text-green-800 dark:bg-green-500/20 dark:text-green-400', order: 4, }, FALSE_POSITIVE: { diff --git a/frontend/src/shared/constants/patrolStatuses.ts b/frontend/src/shared/constants/patrolStatuses.ts index a8a314c..721cd9d 100644 --- a/frontend/src/shared/constants/patrolStatuses.ts +++ b/frontend/src/shared/constants/patrolStatuses.ts @@ -29,49 +29,56 @@ export const PATROL_STATUSES: Record = { code: 'IN_PURSUIT', i18nKey: 'patrolStatus.IN_PURSUIT', fallback: { ko: '추적중', en: 'In Pursuit' }, - classes: 'bg-red-500/20 text-red-400 border-red-500/30', + classes: + 'bg-red-100 text-red-800 border-red-300 dark:bg-red-500/20 dark:text-red-400 dark:border-red-500/30', order: 1, }, INSPECTING: { code: 'INSPECTING', i18nKey: 'patrolStatus.INSPECTING', fallback: { ko: '검문중', en: 'Inspecting' }, - classes: 'bg-orange-500/20 text-orange-400 border-orange-500/30', + classes: + 'bg-orange-100 text-orange-800 border-orange-300 dark:bg-orange-500/20 dark:text-orange-400 dark:border-orange-500/30', order: 2, }, ON_PATROL: { code: 'ON_PATROL', i18nKey: 'patrolStatus.ON_PATROL', fallback: { ko: '초계중', en: 'On Patrol' }, - classes: 'bg-blue-500/20 text-blue-400 border-blue-500/30', + classes: + 'bg-blue-100 text-blue-800 border-blue-300 dark:bg-blue-500/20 dark:text-blue-400 dark:border-blue-500/30', order: 3, }, RETURNING: { code: 'RETURNING', i18nKey: 'patrolStatus.RETURNING', fallback: { ko: '귀항중', en: 'Returning' }, - classes: 'bg-purple-500/20 text-purple-400 border-purple-500/30', + classes: + 'bg-purple-100 text-purple-800 border-purple-300 dark:bg-purple-500/20 dark:text-purple-400 dark:border-purple-500/30', order: 4, }, AVAILABLE: { code: 'AVAILABLE', i18nKey: 'patrolStatus.AVAILABLE', fallback: { ko: '가용', en: 'Available' }, - classes: 'bg-green-500/20 text-green-400 border-green-500/30', + classes: + 'bg-green-100 text-green-800 border-green-300 dark:bg-green-500/20 dark:text-green-400 dark:border-green-500/30', order: 5, }, STANDBY: { code: 'STANDBY', i18nKey: 'patrolStatus.STANDBY', fallback: { ko: '대기', en: 'Standby' }, - classes: 'bg-slate-500/20 text-slate-400 border-slate-500/30', + classes: + 'bg-slate-100 text-slate-700 border-slate-300 dark:bg-slate-500/20 dark:text-slate-400 dark:border-slate-500/30', order: 6, }, MAINTENANCE: { code: 'MAINTENANCE', i18nKey: 'patrolStatus.MAINTENANCE', fallback: { ko: '정비중', en: 'Maintenance' }, - classes: 'bg-yellow-500/20 text-yellow-400 border-yellow-500/30', + classes: + 'bg-yellow-100 text-yellow-800 border-yellow-300 dark:bg-yellow-500/20 dark:text-yellow-400 dark:border-yellow-500/30', order: 7, }, };