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,
},
};