diff --git a/CLAUDE.md b/CLAUDE.md index 348f5b3..3cbe76c 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -127,6 +127,28 @@ wing/ ## 진행 중 작업 (완료 후 삭제) +### 폰트 크기 업스케일 작업 (진행 중) + +반드시 `memory/font-upscale-plan.md`를 읽고 Phase 진행 상황을 확인할 것. + +**토큰 변경 매핑 (이름 유지, 값만 변경):** +- `caption`/`label-2`/`title-6`: 11px → **12px** (0.75rem) +- `label-1`/`title-5`: 12px → **13px** (0.8125rem) +- `body-2`/`title-4`: 13px → **14px** (0.875rem) +- `body-1`/`title-3`: 14px → **16px** (1rem) + +**네비게이션 클래스 교체:** +- TopBar 메인탭: `text-title-4` → `text-title-2` (16px) +- SubMenuBar 서브탭: `text-title-5` → `text-title-4` (14px) + +**작업 범위:** +- Phase 1: tailwind.config.js + base.css 토큰 값 수정 +- Phase 2: components.css 하드코딩(27곳) + wing.css `.wing-tab` text-xs→text-caption +- Phase 3: TopBar.tsx + SubMenuBar.tsx 클래스 교체 +- Phase 4: text-xs→text-caption, text-sm→text-body-2 스크립트 교체 (design 페이지 제외, 608건) +- Phase 5: prediction 탭 인라인 fontSize 수정 +- Phase 6 (보류): wing-header-bar 패딩 — 폰트 변경 후 유저 확인 후 진행 + ### 디자인 시스템 폰트+색상 통일 작업 compact 후 반드시 `memory/design-system-work.md`를 읽고 작업 상태(완료/미완료 컴포넌트)를 확인할 것. diff --git a/frontend/src/common/components/auth/LoginPage.tsx b/frontend/src/common/components/auth/LoginPage.tsx index 6413cf1..717c7ec 100644 --- a/frontend/src/common/components/auth/LoginPage.tsx +++ b/frontend/src/common/components/auth/LoginPage.tsx @@ -120,7 +120,7 @@ export function LoginPage() {
- + setActiveSubTab(item.id)} className={` - px-4 py-2.5 text-title-5 font-medium transition-all duration-200 + px-4 py-2.5 text-title-4 font-medium transition-all duration-200 font-korean tracking-navigation ${activeSubTab === item.id ? 'text-color-accent' : 'text-fg-sub hover:text-fg'} `} diff --git a/frontend/src/common/components/layout/TopBar.tsx b/frontend/src/common/components/layout/TopBar.tsx index ca22afd..2168bfd 100755 --- a/frontend/src/common/components/layout/TopBar.tsx +++ b/frontend/src/common/components/layout/TopBar.tsx @@ -56,11 +56,7 @@ export function TopBar({ activeTab, onTabChange }: TopBarProps) { className="flex items-center hover:opacity-80 transition-opacity cursor-pointer" title="홈으로 이동" > - WING 해양환경 위기대응 + WING 해양환경 위기대응 {/* Divider */} @@ -87,7 +83,7 @@ export function TopBar({ activeTab, onTabChange }: TopBarProps) { onClick={handleClick} title={tab.label} className={` - px-2.5 xl:px-4 py-2 text-title-4 font-bold transition-all duration-200 + px-2.5 xl:px-4 py-2 text-title-2 font-bold transition-all duration-200 font-korean tracking-navigation border-b-2 border-transparent ${isIncident ? 'ml-1' : ''} ${isMonitor ? 'ml-1 flex items-center gap-1.5' : ''} @@ -127,7 +123,7 @@ export function TopBar({ activeTab, onTabChange }: TopBarProps) { {/* Right Section */}
{/* Status Badge */} - {/*
+ {/*
사고 진행중
*/} diff --git a/frontend/src/common/components/map/BacktrackReplayBar.tsx b/frontend/src/common/components/map/BacktrackReplayBar.tsx index 246fa18..dfe63cc 100755 --- a/frontend/src/common/components/map/BacktrackReplayBar.tsx +++ b/frontend/src/common/components/map/BacktrackReplayBar.tsx @@ -141,7 +141,7 @@ export function BacktrackReplayBar({ className="w-2 h-2 rounded-full bg-color-tertiary" style={{ boxShadow: '0 0 8px rgba(168,85,247,0.5)' }} /> - 역추적 리플레이 + 역추적 리플레이
@@ -180,7 +180,7 @@ export function BacktrackReplayBar({ {/* Play/Pause */} @@ -1575,7 +1578,7 @@ function MapLegend({ className="flex items-center gap-1.5 mt-2 rounded" style={{ padding: '6px', background: 'rgba(168,85,247,0.08)' }} > -
🧭
+
🧭
풍향 (방사형)
@@ -1888,7 +1891,9 @@ function BacktrackReplayBar({ minWidth: '340px', }} > -
{progress.toFixed(0)}%
+
+ {progress.toFixed(0)}% +
{ {/* ── 섹션 1: 헤더 ── */}

Components @@ -244,7 +244,7 @@ export const ButtonContent = ({ theme }: ButtonContentProps) => {

- + 텍스트 + 아이콘 버튼
@@ -298,7 +298,7 @@ export const ButtonContent = ({ theme }: ButtonContentProps) => {
- + 아이콘 전용 버튼
@@ -339,7 +339,7 @@ export const ButtonContent = ({ theme }: ButtonContentProps) => {
{/* 라벨 */} {size.label} @@ -349,7 +349,7 @@ export const ButtonContent = ({ theme }: ButtonContentProps) => {
-

+

모든 컬러 토큰은{' '} Property-Role-Variant 3계층 구조를 따릅니다. Property는 색상이 적용되는 CSS 속성, Role은 의미 기반 역할, Variant는 상태 @@ -551,17 +551,17 @@ export const ColorPaletteContent = ({ theme }: ColorPaletteContentProps) => { }} > {row.prop}

-
+
{row.desc}
- + {row.example}
@@ -581,7 +581,7 @@ export const ColorPaletteContent = ({ theme }: ColorPaletteContentProps) => { style={{ border: `1px solid ${dividerColor}` }} >
{ }} > {row.name} - + {row.desc}
@@ -626,7 +626,7 @@ export const ColorPaletteContent = ({ theme }: ColorPaletteContentProps) => { style={{ border: `1px solid ${dividerColor}` }} >
{ }} > {row.name} - + {row.desc}
@@ -672,7 +672,7 @@ export const ColorPaletteContent = ({ theme }: ColorPaletteContentProps) => {

Semantic Tokens

-

+

용도에 따라 의미를 부여한 토큰. 테마 전환 시 값이 변경됩니다.

@@ -745,7 +745,7 @@ export const ColorPaletteContent = ({ theme }: ColorPaletteContentProps) => { }, ].map((group) => (
-

+

{group.title}

{ > {/* 헤더 */}
{ }} > {tk.legacy} {tk.name} - + {tk.desc} - + {tk.value}
@@ -804,7 +804,7 @@ export const ColorPaletteContent = ({ theme }: ColorPaletteContentProps) => { flexShrink: 0, }} /> - + {hexToRgb(tk.value)}
@@ -823,7 +823,7 @@ export const ColorPaletteContent = ({ theme }: ColorPaletteContentProps) => {

Palette Tokens

-

+

fg · bg · stroke 모든 맥락에서 사용되는 색상 원본. Property 접두사 없이{' '} --color-* @@ -836,7 +836,7 @@ export const ColorPaletteContent = ({ theme }: ColorPaletteContentProps) => { style={{ border: `1px solid ${dividerColor}` }} >

{ backgroundColor: isDark ? 'rgba(255,255,255,0.02)' : '#fafafa', }} > - + {tk.legacy} {tk.name} - + {tk.value}
@@ -905,11 +908,11 @@ export const ColorPaletteContent = ({ theme }: ColorPaletteContentProps) => { flexShrink: 0, }} /> - + {hexToRgb(tk.value)}
- + {tk.desc}
@@ -925,7 +928,7 @@ export const ColorPaletteContent = ({ theme }: ColorPaletteContentProps) => {

Non-color Tokens

-

+

타이포그래피, 라운딩 등 색상 외 토큰.

@@ -934,7 +937,7 @@ export const ColorPaletteContent = ({ theme }: ColorPaletteContentProps) => { style={{ border: `1px solid ${dividerColor}` }} >
{ backgroundColor: isDark ? 'rgba(255,255,255,0.02)' : '#fafafa', }} > - + {tk.legacy} {tk.name} { > {tk.category} - + {tk.desc}
@@ -1015,7 +1021,7 @@ export const ColorPaletteContent = ({ theme }: ColorPaletteContentProps) => {

프라이머리 색상(primary color)

-

+

Primary 색상은 해양 방제 시스템의 핵심 인터랙션 요소에 사용됩니다. Cyan~Blue 그라디언트가 주요 액션 버튼과 강조 요소에 적용됩니다.

@@ -1023,7 +1029,7 @@ export const ColorPaletteContent = ({ theme }: ColorPaletteContentProps) => {
{/* Light Mode */}
-

+

Light Mode

{ {/* Dark Mode */}
-

+

Dark Mode

{

세컨더리 색상(secondary color)

-

+

Secondary 색상은 UI의 배경과 구조적 요소에 사용됩니다. Navy 계열로 다크 모드의 깊이감과 계층 구조를 표현합니다.

@@ -1075,7 +1081,7 @@ export const ColorPaletteContent = ({ theme }: ColorPaletteContentProps) => {
{/* Light Mode */}
-

+

Light Mode

{ {/* Dark Mode */}
-

+

Dark Mode

{

그레이 색상(gray color) / 네추럴, 중립 색상

-

+

Gray 색상은 주로 배경, 텍스트, 구분 선에 사용되며, 시각적 집중을 방해하지 않고 콘텐츠에 초점을 맞추도록 도와주는 중립적인 색상이다.

-

+

표준형 스타일의 그레이 색상은 주요 색상과 선명한 모드에서의 조화를 고려해 블루 그레이 계열을 사용한다.

@@ -1141,7 +1147,7 @@ export const ColorPaletteContent = ({ theme }: ColorPaletteContentProps) => {

Transparent

-

+

투명도와 음영을 활용하여 정보의 집중도를 조절합니다. 배경의 음영 처리는 투명도 65%를 사용합니다.

@@ -1174,12 +1180,12 @@ export const ColorPaletteContent = ({ theme }: ColorPaletteContentProps) => {

Primitive

-

+

UI 전반에서 사용하는 기본 색조 팔레트. 테마와 무관하게 고정된 값입니다.

@@ -1214,17 +1220,17 @@ export const ColorPaletteContent = ({ theme }: ColorPaletteContentProps) => { /> {/* 토큰명 */} {token.name} {/* HEX + RGB */}
-
+
{token.hex}
-
+
{hexToRgb(token.hex)}
diff --git a/frontend/src/pages/design/ComponentsContent.tsx b/frontend/src/pages/design/ComponentsContent.tsx index 663231e..efa2d6c 100644 --- a/frontend/src/pages/design/ComponentsContent.tsx +++ b/frontend/src/pages/design/ComponentsContent.tsx @@ -13,7 +13,7 @@ export const ComponentsContent = () => { > 시스템 컴포넌트 카탈로그 -

+

WING-OPS 해상 물류를 위한 시각적 아이덴티티 시스템입니다. 정밀도와 미션 크리티컬한 운영을 위해 설계된 고밀도 산업용 인터페이스입니다.

diff --git a/frontend/src/pages/design/ComponentsOverview.tsx b/frontend/src/pages/design/ComponentsOverview.tsx index 731664a..ce1a119 100644 --- a/frontend/src/pages/design/ComponentsOverview.tsx +++ b/frontend/src/pages/design/ComponentsOverview.tsx @@ -256,7 +256,7 @@ const ComponentsOverview = ({ theme, onNavigate }: ComponentsOverviewProps) => { {/* ── 헤더 영역 ── */}
Components @@ -264,7 +264,7 @@ const ComponentsOverview = ({ theme, onNavigate }: ComponentsOverviewProps) => {

Overview

-

+

재사용 가능한 UI 컴포넌트 카탈로그입니다.

@@ -307,7 +307,10 @@ const ComponentsOverview = ({ theme, onNavigate }: ComponentsOverviewProps) => { {/* 카드 라벨 */}
- + {card.label}
diff --git a/frontend/src/pages/design/DesignContent.tsx b/frontend/src/pages/design/DesignContent.tsx index 69c9b36..007c8a8 100644 --- a/frontend/src/pages/design/DesignContent.tsx +++ b/frontend/src/pages/design/DesignContent.tsx @@ -154,7 +154,7 @@ export const DesignContent = ({ theme }: DesignContentProps) => { style={{ backgroundColor: t.textAccent, boxShadow: t.systemActiveShadow }} /> System Active @@ -192,11 +192,14 @@ export const DesignContent = ({ theme }: DesignContentProps) => { /> {/* 정보 */}
- + {item.token} {item.hex} @@ -233,7 +236,7 @@ export const DesignContent = ({ theme }: DesignContentProps) => { {item.token} {item.hex} @@ -263,7 +266,7 @@ export const DesignContent = ({ theme }: DesignContentProps) => { {item.token} {item.sampleText} - + {item.desc}
@@ -297,7 +300,7 @@ export const DesignContent = ({ theme }: DesignContentProps) => { />
{item.name} @@ -435,7 +438,7 @@ export const DesignContent = ({ theme }: DesignContentProps) => {
{/* radius-sm */}
- + {t.radiusSmLabel}
{ Small Elements

Applied to tactical buttons, search inputs, and micro-cards for a precise, sharp @@ -463,7 +466,7 @@ export const DesignContent = ({ theme }: DesignContentProps) => {

{/* radius-md */}
- + {t.radiusMdLabel}
{ Structural Panels

Applied to telemetry cards, floating modals, and primary operational panels to diff --git a/frontend/src/pages/design/FloatContent.tsx b/frontend/src/pages/design/FloatContent.tsx index 020fac6..bfca117 100644 --- a/frontend/src/pages/design/FloatContent.tsx +++ b/frontend/src/pages/design/FloatContent.tsx @@ -50,7 +50,10 @@ export const FloatContent = ({ theme }: FloatContentProps) => {

Float

-

+

화면 위에 떠서 표시되는 UI 패턴 카탈로그 — Modal, Dropdown, Overlay, Toast

@@ -70,7 +73,7 @@ export const FloatContent = ({ theme }: FloatContentProps) => { }} > {label} diff --git a/frontend/src/pages/design/FoundationsOverview.tsx b/frontend/src/pages/design/FoundationsOverview.tsx index 1837f0b..ef03049 100644 --- a/frontend/src/pages/design/FoundationsOverview.tsx +++ b/frontend/src/pages/design/FoundationsOverview.tsx @@ -174,7 +174,7 @@ const FoundationsOverview = ({ theme, onNavigate }: FoundationsOverviewProps) => {/* ── 헤더 영역 ── */}
Foundations @@ -182,7 +182,7 @@ const FoundationsOverview = ({ theme, onNavigate }: FoundationsOverviewProps) =>

Overview

-

+

디자인의 기반이 되는 핵심 요소 사용 기준입니다.

@@ -225,7 +225,10 @@ const FoundationsOverview = ({ theme, onNavigate }: FoundationsOverviewProps) => {/* 카드 라벨 */}
- + {card.label}
diff --git a/frontend/src/pages/design/LayoutContent.tsx b/frontend/src/pages/design/LayoutContent.tsx index 82035d8..0a180f1 100644 --- a/frontend/src/pages/design/LayoutContent.tsx +++ b/frontend/src/pages/design/LayoutContent.tsx @@ -324,7 +324,7 @@ export const LayoutContent = ({ theme }: LayoutContentProps) => {

Layout

-

+

WING-OPS는 데스크톱 전용 고정 뷰포트 애플리케이션입니다. 화면 전체를 채우는 고정 레이아웃(100vh)으로, flex 기반의 패널 구조를 사용합니다. KRDS 가이드라인을 기반으로 xlarge / xxlarge 구간에 최적화되어 있습니다. @@ -364,7 +364,7 @@ export const LayoutContent = ({ theme }: LayoutContentProps) => {

Breakpoint

-

+

화면 크기에 따라 반응형 레이아웃을 사용하여 환경에 최적화된 구조로 표시됩니다. WING-OPS 사용 구간(xl, 2xl)은 cyan으로 강조되어 있습니다.

@@ -499,7 +499,7 @@ export const LayoutContent = ({ theme }: LayoutContentProps) => { borderColor: isDark ? 'rgba(76,215,246,0.45)' : 'rgba(6,182,212,0.40)', }} /> - + WING-OPS 사용 중
@@ -511,7 +511,7 @@ export const LayoutContent = ({ theme }: LayoutContentProps) => { borderColor: isDark ? 'rgba(140,144,159,0.25)' : 'rgba(148,163,184,0.30)', }} /> - + 미지원 (1280px 미만)
@@ -525,7 +525,7 @@ export const LayoutContent = ({ theme }: LayoutContentProps) => {

Grid

-

+

컬럼, 마진, 거터로 구성된 그리드 시스템입니다. 데스크톱 전용으로 xl / 2xl 두 구간만 지원합니다.

@@ -548,7 +548,7 @@ export const LayoutContent = ({ theme }: LayoutContentProps) => { style={{ borderColor: isDark ? 'rgba(66,71,84,0.20)' : '#e2e8f0' }} >
- + Breakpoint {
- + Width - + {spec.width}
@@ -683,7 +683,7 @@ export const LayoutContent = ({ theme }: LayoutContentProps) => { - + 1280px 미만 미지원 — Mobile / Tablet 구간(xs / s / md / lg)은 데스크톱 전용 운영 정책에 따라 지원하지 않습니다. @@ -696,7 +696,7 @@ export const LayoutContent = ({ theme }: LayoutContentProps) => {

App Shell

-

+

WING-OPS 애플리케이션의 기본 레이아웃 구조와 KRDS Sub-page 영역 매핑입니다.

@@ -720,7 +720,7 @@ export const LayoutContent = ({ theme }: LayoutContentProps) => { }} >
- + TopBar {

Spacing

-

+

UI 요소 간의 간격과 여백을 정의하여 콘텐츠의 위계와 가독성을 조율합니다. Tailwind spacing 토큰과 직결되며, 막대 길이는 실제 px 비율입니다.

@@ -1000,7 +1000,7 @@ export const LayoutContent = ({ theme }: LayoutContentProps) => {

4pt Grid

-

+

모든 여백과 간격을 4point 단위로 설정해 규칙성을 확보합니다. 컴팩트한 컴포넌트의 경우, 2의 배수 단위를 제한적으로 사용합니다.

@@ -1048,7 +1048,7 @@ export const LayoutContent = ({ theme }: LayoutContentProps) => { > {item.label}
- + {item.text}
@@ -1145,7 +1145,10 @@ export const LayoutContent = ({ theme }: LayoutContentProps) => { minWidth: '180px', }} > - + 카드 타이틀 @@ -1185,7 +1188,7 @@ export const LayoutContent = ({ theme }: LayoutContentProps) => { 디자인 시스템 진실 소스
-

+

UI 요소의 레이어 스택 순서입니다. 높은 z-index가 위에 표시되며, 이 값은 디자인 시스템의 이상적 설계 값으로 실제 코드는 이 값에 맞춰 정정되어야 합니다.

@@ -1216,7 +1219,7 @@ export const LayoutContent = ({ theme }: LayoutContentProps) => { className="w-2 h-2 rounded-full shrink-0" style={{ backgroundColor: layer.color }} /> - + {layer.name} @@ -1234,7 +1237,7 @@ export const LayoutContent = ({ theme }: LayoutContentProps) => {

Reference

-

+

App Shell CSS 클래스와 KRDS Grid 규칙 비교 — 코드 작성 시 참조용입니다.

diff --git a/frontend/src/pages/design/RadiusContent.tsx b/frontend/src/pages/design/RadiusContent.tsx index 0f34e49..04d3e89 100644 --- a/frontend/src/pages/design/RadiusContent.tsx +++ b/frontend/src/pages/design/RadiusContent.tsx @@ -70,17 +70,17 @@ export const RadiusContent = ({ theme }: RadiusContentProps) => {

Radius

-

+

Radius는 컴포넌트 혹은 콘텐츠 모서리의 둥글기를 표현합니다.

-

+

Radius는 UI 구성 요소의 모서리를 둥글게 처리하여 부드럽고 현대적인 느낌을 제공합니다. 일관된 Radius 값은 브랜드 아이덴티티를 강화하고, 사용자 경험을 향상시키며, 다양한 화면과 컨텍스트에서 시각적 일관성을 유지하는 데 중요한 역할을 합니다.

  • @@ -203,7 +203,7 @@ export const RadiusContent = ({ theme }: RadiusContentProps) => {

    컴포넌트 매핑

    -

    +

    wing.css 컴포넌트 클래스에 적용된 Radius 토큰입니다.

@@ -233,7 +233,7 @@ export const RadiusContent = ({ theme }: RadiusContentProps) => { {/* 정보 */}
- + {item.className}
diff --git a/frontend/src/pages/design/TextFieldContent.tsx b/frontend/src/pages/design/TextFieldContent.tsx index 9ec4386..2891f0a 100644 --- a/frontend/src/pages/design/TextFieldContent.tsx +++ b/frontend/src/pages/design/TextFieldContent.tsx @@ -207,7 +207,7 @@ export const TextFieldContent = ({ theme }: TextFieldContentProps) => { {/* ── 섹션 1: 헤더 ── */}

Components @@ -225,7 +225,7 @@ export const TextFieldContent = ({ theme }: TextFieldContentProps) => {

Input Field

-

+

단일 행 텍스트를 입력받는 필드입니다.

@@ -246,7 +246,7 @@ export const TextFieldContent = ({ theme }: TextFieldContentProps) => { {/* Prefix label */}
Prefix @@ -272,7 +272,7 @@ export const TextFieldContent = ({ theme }: TextFieldContentProps) => { {/* Input label */}
Input @@ -295,7 +295,7 @@ export const TextFieldContent = ({ theme }: TextFieldContentProps) => { {/* Suffix label */}
Suffix @@ -377,7 +377,7 @@ export const TextFieldContent = ({ theme }: TextFieldContentProps) => { {/* Suffix 텍스트 */} 원 @@ -402,7 +402,7 @@ export const TextFieldContent = ({ theme }: TextFieldContentProps) => { }} > Container @@ -437,7 +437,7 @@ export const TextFieldContent = ({ theme }: TextFieldContentProps) => { style={{ width: '1px', height: '10px', backgroundColor: annotationColor }} /> Clear Button @@ -468,7 +468,7 @@ export const TextFieldContent = ({ theme }: TextFieldContentProps) => { Container
-

+

입력 필드의 외곽 영역입니다. 테두리, 곡률, 내부 여백을 정의합니다.

@@ -519,13 +519,13 @@ export const TextFieldContent = ({ theme }: TextFieldContentProps) => {
-

+

height: 44px (Medium)

-

+

padding: 12px (좌우)

-

+

border-radius: 6px

@@ -543,14 +543,14 @@ export const TextFieldContent = ({ theme }: TextFieldContentProps) => { Placeholder
-

+

값이 입력되지 않았을 때 표시되는 안내 텍스트입니다. 입력 시 사라집니다.

{/* 플레이스홀더 있는 필드 */}
- + 플레이스홀더 있음
{ {/* 빈 필드 (플레이스홀더 없음) */}
- + 플레이스홀더 없음
{ Label
-

+

입력 필드의 용도를 설명하는 텍스트입니다. 필수 항목은 * 표시로 구분합니다.

{/* 일반 라벨 */}
- + 이름
{ {/* 필수 라벨 */}
- + 이메일 *
{ Input Text
-

+

사용자가 실제로 입력한 텍스트입니다. 플레이스홀더보다 진한 색상으로 표시됩니다.

@@ -673,7 +679,10 @@ export const TextFieldContent = ({ theme }: TextFieldContentProps) => { > 홍길동
-
+
font-size: 14px color: textPrimary font-weight: 400 @@ -692,14 +701,14 @@ export const TextFieldContent = ({ theme }: TextFieldContentProps) => { Clear Icon
-

+

입력값이 있을 때 표시되는 초기화 버튼입니다. 클릭 시 입력값을 삭제합니다.

{/* 텍스트 입력 + Clear 아이콘 표시 */}
- + 입력값 있음 (Clear 표시)
{ {/* 빈 상태 (Clear 미표시) */}
- + 입력값 없음 (Clear 미표시)
{ Helper Text
-

+

입력 필드 하단에 표시되는 보조 텍스트입니다. 안내 또는 에러 메시지로 사용됩니다.

@@ -787,7 +796,7 @@ export const TextFieldContent = ({ theme }: TextFieldContentProps) => { > 비밀번호
- + 영문, 숫자 포함 8자 이상
@@ -807,7 +816,7 @@ export const TextFieldContent = ({ theme }: TextFieldContentProps) => { > 비밀번호
- + 필수 입력 항목입니다.
@@ -828,7 +837,7 @@ export const TextFieldContent = ({ theme }: TextFieldContentProps) => {
{/* 왼쪽: State 라벨 + 뱃지 */}
- + State {

Text Area

-

+

여러 줄의 텍스트를 입력받는 필드입니다.

@@ -911,7 +920,7 @@ export const TextFieldContent = ({ theme }: TextFieldContentProps) => { {/* Input Area label */}
Input Area @@ -933,7 +942,7 @@ export const TextFieldContent = ({ theme }: TextFieldContentProps) => { {/* Placeholder label */}
Placeholder @@ -955,7 +964,7 @@ export const TextFieldContent = ({ theme }: TextFieldContentProps) => { {/* Character Counter label */}
Character Counter @@ -1042,7 +1051,7 @@ export const TextFieldContent = ({ theme }: TextFieldContentProps) => { }} > Container @@ -1075,7 +1084,7 @@ export const TextFieldContent = ({ theme }: TextFieldContentProps) => { style={{ width: '1px', height: '10px', backgroundColor: annotationColor }} /> Resize Handle @@ -1103,7 +1112,7 @@ export const TextFieldContent = ({ theme }: TextFieldContentProps) => { Container
-

+

텍스트 영역의 외곽 컨테이너입니다. 기본 높이 112px이며 사용자가 리사이즈할 수 있습니다.

@@ -1154,16 +1163,16 @@ export const TextFieldContent = ({ theme }: TextFieldContentProps) => {
-

+

height: 112px (default)

-

+

padding: 12px

-

+

border-radius: 6px

-

+

resize: vertical

@@ -1181,14 +1190,14 @@ export const TextFieldContent = ({ theme }: TextFieldContentProps) => { Placeholder
-

+

값이 입력되지 않았을 때 표시되는 안내 텍스트입니다.

{/* 플레이스홀더 있는 TextArea */}
- + 플레이스홀더 있음
{ {/* 빈 TextArea */}
- + 플레이스홀더 없음
{ Label
-

+

텍스트 영역의 용도를 설명하는 라벨입니다.

{/* 기본 라벨 */}
- + 내용
{ {/* 필수(*) 라벨 */}
- + 비고 *
{ Input Text
-

+

사용자가 입력한 여러 줄의 텍스트입니다.

@@ -1316,7 +1331,10 @@ export const TextFieldContent = ({ theme }: TextFieldContentProps) => { > {'오늘 점검 내용을 기록합니다.\n상세 내용은 아래와 같습니다.'}
-
+
font-size: 14px color: textPrimary line-height: 1.6 @@ -1335,14 +1353,14 @@ export const TextFieldContent = ({ theme }: TextFieldContentProps) => { Clear Icon
-

+

입력값 초기화 버튼입니다. 텍스트 영역 우상단에 표시됩니다.

{/* 텍스트 있는 상태 (Clear 표시) */}
- + 입력값 있음 (Clear 표시)
{ {/* 빈 상태 (Clear 미표시) */}
- + 입력값 없음 (Clear 미표시)
{ Helper Text
-

+

텍스트 영역 하단의 도움말 또는 에러 메시지입니다.

@@ -1434,10 +1452,10 @@ export const TextFieldContent = ({ theme }: TextFieldContentProps) => { 내용을 입력하세요
- + 상세 내용을 입력해 주세요 - + 0/500
@@ -1459,7 +1477,7 @@ export const TextFieldContent = ({ theme }: TextFieldContentProps) => { > 내용을 입력하세요
- + 필수 입력 항목입니다.
@@ -1480,7 +1498,7 @@ export const TextFieldContent = ({ theme }: TextFieldContentProps) => {
{/* 왼쪽: State 라벨 + 뱃지 */}
- + State {

Typography

-

+

WING-OPS 인터페이스에서 사용되는 타이포그래피 체계입니다. 폰트 패밀리, 크기, 두께를 토큰과 컴포넌트 클래스로 정의하여 시각적 계층 구조와 일관성을 유지합니다.

-

+

개요

  • @@ -337,7 +337,7 @@ export const TypographyContent = ({ theme }: TypographyContentProps) => {

    글꼴

    -

    +

    사용자의 디바이스 환경을 고려하여, 시스템 폰트와 웹 폰트를 조합하여 사용합니다. 한국어 UI에 최적화된 폰트 스택으로 다양한 기기에서 일관된 가독성을 보장합니다.

    @@ -352,7 +352,7 @@ export const TypographyContent = ({ theme }: TypographyContentProps) => { }} >
                 font-family
    @@ -390,7 +390,7 @@ export const TypographyContent = ({ theme }: TypographyContentProps) => {
                       
{ > {font.stack}
-

{font.usage}

+

{font.usage}

Regular @@ -421,7 +421,7 @@ export const TypographyContent = ({ theme }: TypographyContentProps) => {

타입 스케일

-

+

Display, Heading, Body, Navigation, Label의 5가지 용도 카테고리에 맞게 조합하여 사용합니다.

@@ -434,7 +434,7 @@ export const TypographyContent = ({ theme }: TypographyContentProps) => {

{category.name}

-

+

{category.description}

@@ -445,7 +445,7 @@ export const TypographyContent = ({ theme }: TypographyContentProps) => { style={{ border: `1px solid ${isDark ? 'rgba(66,71,84,0.20)' : '#e2e8f0'}` }} >
{ backgroundColor: isDark ? 'rgba(255,255,255,0.02)' : '#fafafa', }} > - + {row.token} - + {row.px} - + {row.weight} {`${(row.lineHeight * 100).toFixed(0)}%`} - + {row.letterSpacing} { >
{row.token} @@ -533,7 +536,7 @@ export const TypographyContent = ({ theme }: TypographyContentProps) => { {row.sample}
-
+
{row.role}
@@ -551,7 +554,7 @@ export const TypographyContent = ({ theme }: TypographyContentProps) => {

폰트 두께 토큰

-

+

기본 두께 Regular(400), 강조 Bold(700). Medium(500)은 레이블과 소제목, Thin(300)은 장식적 대형 텍스트에 사용합니다.

@@ -561,7 +564,7 @@ export const TypographyContent = ({ theme }: TypographyContentProps) => { style={{ border: `1px solid ${isDark ? 'rgba(66,71,84,0.20)' : '#e2e8f0'}` }} >
{ backgroundColor: isDark ? 'rgba(255,255,255,0.02)' : '#fafafa', }} > - + {row.token} - + {row.value} - + {row.name} {row.preview} @@ -632,7 +638,7 @@ export const TypographyContent = ({ theme }: TypographyContentProps) => {

줄 높이 토큰

-

+

대형 텍스트는 타이트하게(1.3), 본문은 여유롭게(1.6). 가독성과 공간 효율의 균형을 맞춥니다.

@@ -642,7 +648,7 @@ export const TypographyContent = ({ theme }: TypographyContentProps) => { style={{ border: `1px solid ${isDark ? 'rgba(66,71,84,0.20)' : '#e2e8f0'}` }} >
{ backgroundColor: isDark ? 'rgba(255,255,255,0.02)' : '#fafafa', }} > - + {row.token} - + {row.value} - + {row.pct} - + {row.desc}
@@ -700,7 +709,7 @@ export const TypographyContent = ({ theme }: TypographyContentProps) => {

자간 토큰

-

+

카테고리별로 자간을 정의합니다. Display는 넓게, Body는 기본값을 사용합니다.

@@ -709,7 +718,7 @@ export const TypographyContent = ({ theme }: TypographyContentProps) => { style={{ border: `1px solid ${isDark ? 'rgba(66,71,84,0.20)' : '#e2e8f0'}` }} >
{ backgroundColor: isDark ? 'rgba(255,255,255,0.02)' : '#fafafa', }} > - + {row.token} - + {row.value} { > {row.tw} - + {row.category}
diff --git a/frontend/src/pages/design/components/ButtonCatalogSection.tsx b/frontend/src/pages/design/components/ButtonCatalogSection.tsx index bd8fe8d..f4ef9e4 100644 --- a/frontend/src/pages/design/components/ButtonCatalogSection.tsx +++ b/frontend/src/pages/design/components/ButtonCatalogSection.tsx @@ -167,7 +167,7 @@ export const ButtonCatalogSection = () => {
제어 인터페이스: 버튼 @@ -185,7 +185,7 @@ export const ButtonCatalogSection = () => { className="pt-px pr-2 pb-[17.5px] pl-2 flex flex-col gap-0 items-start justify-start flex-1 min-w-0 relative" >
{header} @@ -207,7 +207,7 @@ export const ButtonCatalogSection = () => { > {/* 버튼 유형 레이블 */}
-
+
{row.label}
diff --git a/frontend/src/pages/design/components/CardSection.tsx b/frontend/src/pages/design/components/CardSection.tsx index 4d6118c..17d1627 100644 --- a/frontend/src/pages/design/components/CardSection.tsx +++ b/frontend/src/pages/design/components/CardSection.tsx @@ -129,7 +129,7 @@ export const CardSection = () => {
24.8
-
+
노트 (knots)
diff --git a/frontend/src/pages/design/components/IconBadgeSection.tsx b/frontend/src/pages/design/components/IconBadgeSection.tsx index 87c1953..bb947a9 100644 --- a/frontend/src/pages/design/components/IconBadgeSection.tsx +++ b/frontend/src/pages/design/components/IconBadgeSection.tsx @@ -61,7 +61,7 @@ export const IconBadgeSection = () => {
마이크로 컨트롤: 아이콘 버튼 @@ -113,7 +113,7 @@ export const IconBadgeSection = () => {
마이크로 컨트롤: 아이콘 버튼 diff --git a/frontend/src/pages/design/float/FloatDropdownContent.tsx b/frontend/src/pages/design/float/FloatDropdownContent.tsx index 9a3792e..2391c4d 100644 --- a/frontend/src/pages/design/float/FloatDropdownContent.tsx +++ b/frontend/src/pages/design/float/FloatDropdownContent.tsx @@ -36,10 +36,10 @@ export const FloatDropdownContent = ({ theme }: FloatDropdownContentProps) => {

Dropdown

-

+

트리거 요소에{' '} { 로 부착되는 선택 목록. 5개 이상의 선택지가 있는 단일 선택에 사용한다. 프로젝트 공통 컴포넌트는{' '} { >

- + 유출 유형 {
- + 예측 알고리즘 {
-

+

위 컴포넌트는{' '} @common/components/ui/ComboBox @@ -373,7 +373,7 @@ export const FloatDropdownContent = ({ theme }: FloatDropdownContentProps) => {

- + {row.desc}
@@ -423,10 +423,16 @@ export const FloatDropdownContent = ({ theme }: FloatDropdownContentProps) => { : t.cardBorder, }} > - + {item.title} - + {item.desc}
diff --git a/frontend/src/pages/design/float/FloatModalContent.tsx b/frontend/src/pages/design/float/FloatModalContent.tsx index 5eed471..0557b78 100644 --- a/frontend/src/pages/design/float/FloatModalContent.tsx +++ b/frontend/src/pages/design/float/FloatModalContent.tsx @@ -88,9 +88,9 @@ export const FloatModalContent = ({ theme }: FloatModalContentProps) => {

Modal

-

+

{ ))}

- + {SIZE_CONFIG[activeSize].desc}
@@ -166,7 +166,7 @@ export const FloatModalContent = ({ theme }: FloatModalContentProps) => {
@@ -480,7 +483,7 @@ export const FloatModalContent = ({ theme }: FloatModalContentProps) => { }} >
- + {item.component}
@@ -496,7 +499,7 @@ export const FloatModalContent = ({ theme }: FloatModalContentProps) => {
- + {item.trigger}
@@ -533,7 +536,10 @@ export const FloatModalContent = ({ theme }: FloatModalContentProps) => { className="flex items-center justify-between px-5 py-4 border-b border-solid shrink-0" style={{ borderColor: modalBorder }} > - + Modal Preview — {SIZE_CONFIG[activeSize].label} ({SIZE_CONFIG[activeSize].width})
-

+

이 모달은{' '} { className="rounded border border-solid px-3 py-2.5" style={{ borderColor: t.cardBorder }} > - + {label}

@@ -582,7 +588,7 @@ export const FloatModalContent = ({ theme }: FloatModalContentProps) => {
-

+

삭제된 데이터는 복구할 수 없습니다. 계속 진행하시겠습니까?

@@ -641,7 +650,7 @@ export const FloatModalContent = ({ theme }: FloatModalContentProps) => {
- + {row.overlay}
- + {row.modal}
@@ -284,7 +284,7 @@ export const FloatOverlayContent = ({ theme }: FloatOverlayContentProps) => { className="rounded-lg border border-solid p-5 flex flex-col gap-4" style={{ backgroundColor: t.cardBg, borderColor: t.cardBorder }} > -

+

ScatPopup은 지도 마커에 앵커된 컨텍스트 팝업이다. Modal(fixed 뷰포트 중앙)과 달리 마커 위치에서 동적으로 좌표를 계산하며, 지도 패닝·줌 시 위치가 함께 업데이트된다. @@ -307,7 +307,7 @@ export const FloatOverlayContent = ({ theme }: FloatOverlayContentProps) => { {item.label} - + {item.value} @@ -323,7 +323,7 @@ export const FloatOverlayContent = ({ theme }: FloatOverlayContentProps) => { borderColor: 'rgba(234,179,8,0.25)', }} > - + 주의: ScatPopup은 MapLibre GL JS의 Popup/Marker 컴포넌트가 아닌 React DOM으로 구현됨. 지도 컨테이너 내부에 position: absolute로 렌더링된다. @@ -377,7 +377,7 @@ export const FloatOverlayContent = ({ theme }: FloatOverlayContentProps) => { }} >

- + {item.component}
@@ -413,7 +413,10 @@ export const FloatOverlayContent = ({ theme }: FloatOverlayContentProps) => {
- + {item.desc}
diff --git a/frontend/src/pages/design/float/FloatToastContent.tsx b/frontend/src/pages/design/float/FloatToastContent.tsx index 05aea63..1f14fb1 100644 --- a/frontend/src/pages/design/float/FloatToastContent.tsx +++ b/frontend/src/pages/design/float/FloatToastContent.tsx @@ -84,10 +84,10 @@ export const FloatToastContent = ({ theme }: FloatToastContentProps) => { 미구현 — 설계 사양
-

+

화면을 차단하지 않는 비파괴적 알림. { 에 위치하며 일정 시간 후 자동으로 사라진다. 현재 프로젝트에서는{' '} { className="rounded-lg border border-solid p-5 flex flex-col gap-4" style={{ backgroundColor: t.cardBg, borderColor: t.cardBorder }} > -

+

버튼 클릭 시 화면 우하단에 Toast가 표시됩니다. 3초 후 자동으로 사라집니다.

@@ -280,7 +280,7 @@ export const FloatToastContent = ({ theme }: FloatToastContentProps) => { {cfg.icon} - + {cfg.label}
@@ -311,7 +311,7 @@ export const FloatToastContent = ({ theme }: FloatToastContentProps) => { className="rounded-lg border border-solid p-5 flex flex-col gap-4" style={{ backgroundColor: t.cardBg, borderColor: t.cardBorder }} > -

+

Toast는 앱 어디서든 호출해야 하므로 Zustand store + useToast hook{' '} 패턴을 권장한다. ToastContainer는 App.tsx 최상위에 한 번만 렌더링한다.

@@ -387,7 +387,7 @@ export const FloatToastContent = ({ theme }: FloatToastContentProps) => { {cfg.icon} - + {toast.message} @@ -162,7 +162,7 @@ export default function BoardMgmtPanel({ initialCategory = '' }: BoardMgmtPanelP @@ -170,7 +170,7 @@ export default function BoardMgmtPanel({ initialCategory = '' }: BoardMgmtPanelP {/* 테이블 */}
- +
diff --git a/frontend/src/tabs/admin/components/CollectHrPanel.tsx b/frontend/src/tabs/admin/components/CollectHrPanel.tsx index b943d1d..5cd324e 100644 --- a/frontend/src/tabs/admin/components/CollectHrPanel.tsx +++ b/frontend/src/tabs/admin/components/CollectHrPanel.tsx @@ -211,7 +211,7 @@ const HEADERS = [ function HrTable({ rows, loading }: { rows: HrCollectItem[]; loading: boolean }) { return (
-
@@ -222,7 +222,7 @@ export default function BoardMgmtPanel({ initialCategory = '' }: BoardMgmtPanelP @@ -234,7 +234,7 @@ export default function BoardMgmtPanel({ initialCategory = '' }: BoardMgmtPanelP diff --git a/frontend/src/tabs/admin/components/CleanupEquipPanel.tsx b/frontend/src/tabs/admin/components/CleanupEquipPanel.tsx index ba1793a..0f60686 100644 --- a/frontend/src/tabs/admin/components/CleanupEquipPanel.tsx +++ b/frontend/src/tabs/admin/components/CleanupEquipPanel.tsx @@ -99,13 +99,15 @@ function CleanupEquipPanel() {

방제장비 현황

-

총 {filtered.length}개 기관

+

+ 총 {filtered.length}개 기관 +

{typeOptions.map((t) => ( @@ -129,7 +131,7 @@ function CleanupEquipPanel() {
조회된 기관이 없습니다.
+
{HEADERS.map((h) => ( @@ -317,10 +317,10 @@ export default function CollectHrPanel() {
{/* 헤더 */}
-

인사정보 수집 현황

+

인사정보 수집 현황

{lastUpdate && ( - + 갱신:{' '} {lastUpdate.toLocaleTimeString('ko-KR', { hour: '2-digit', @@ -332,7 +332,7 @@ export default function CollectHrPanel() {
diff --git a/frontend/src/tabs/admin/components/DispersingZonePanel.tsx b/frontend/src/tabs/admin/components/DispersingZonePanel.tsx index 4f07252..884bd7b 100644 --- a/frontend/src/tabs/admin/components/DispersingZonePanel.tsx +++ b/frontend/src/tabs/admin/components/DispersingZonePanel.tsx @@ -130,7 +130,9 @@ const DispersingZonePanel = () => { onClick={() => handleToggleExpand(zone)} > - {info.label} + + {info.label} + {/* 토글 스위치 */} @@ -487,7 +487,7 @@ const LayerPanel = () => { {/* 오류 메시지 */} {error && ( -
+
{error}
)} @@ -495,7 +495,7 @@ const LayerPanel = () => { {/* 테이블 영역 */}
{loading ? ( -
+
불러오는 중...
) : ( @@ -539,7 +539,7 @@ const LayerPanel = () => {
@@ -551,15 +551,15 @@ const LayerPanel = () => { className="border-b border-stroke hover:bg-[rgba(255,255,255,0.02)] transition-colors" > {/* 번호 */} - {/* 레이어코드 */} {/* 레이어명 */} - + {/* 레이어전체명 */} - {/* 정렬순서 */} - {/* 등록일시 */} @@ -614,13 +614,13 @@ const LayerPanel = () => {
diff --git a/frontend/src/tabs/admin/components/MapBasePanel.tsx b/frontend/src/tabs/admin/components/MapBasePanel.tsx index 50efd74..539f26f 100644 --- a/frontend/src/tabs/admin/components/MapBasePanel.tsx +++ b/frontend/src/tabs/admin/components/MapBasePanel.tsx @@ -78,7 +78,7 @@ function MapBaseModal({
{/* 모달 헤더 */}
-

+

{isEdit ? '지도 수정' : '지도 등록'}

@@ -123,7 +123,7 @@ function MapBaseModal({ onChange={(e) => setField('mapKey', e.target.value)} placeholder="고유 식별 키 (영문/숫자)" disabled={isEdit} - className="w-full px-3 py-2 text-xs bg-bg-elevated border border-stroke rounded-md text-fg placeholder-fg-disabled focus:border-color-accent focus:outline-none font-mono disabled:opacity-50 disabled:cursor-not-allowed" + className="w-full px-3 py-2 text-caption bg-bg-elevated border border-stroke rounded-md text-fg placeholder-fg-disabled focus:border-color-accent focus:outline-none font-mono disabled:opacity-50 disabled:cursor-not-allowed" />
@@ -135,7 +135,7 @@ function MapBaseModal({
데이터가 없습니다. + {(page - 1) * PAGE_SIZE + idx + 1} {item.layerCd}{item.layerNm}{item.layerNm} + {item.layerFullNm} @@ -575,7 +575,7 @@ const LayerPanel = () => { {item.wmsLayerNm ?? -} + {item.sortOrd}
+
@@ -433,7 +433,7 @@ function MapBasePanel() {
번호 @@ -441,7 +441,7 @@ function MapBasePanel() { @@ -452,7 +452,7 @@ function MapBasePanel() {
{!loading && items.length === 0 && ( -
+
등록된 지도가 없습니다.
)} @@ -464,7 +464,7 @@ function MapBasePanel() { @@ -476,7 +476,7 @@ function MapBasePanel() { diff --git a/frontend/src/tabs/admin/components/MenusPanel.tsx b/frontend/src/tabs/admin/components/MenusPanel.tsx index dc9786c..d9e603b 100644 --- a/frontend/src/tabs/admin/components/MenusPanel.tsx +++ b/frontend/src/tabs/admin/components/MenusPanel.tsx @@ -124,7 +124,7 @@ function MenusPanel() { if (loading) { return (
-
메뉴 설정을 불러오는 중...
+
메뉴 설정을 불러오는 중...
); } @@ -136,14 +136,14 @@ function MenusPanel() {

메뉴 관리

-

+

메뉴 표시 여부, 순서, 라벨, 아이콘을 관리합니다

@@ -815,7 +815,7 @@ function UserPermTab({ roles, permTree, rolePerms }: UserPermTabProps) { onFocus={() => setShowDropdown(true)} placeholder={loadingUsers ? '불러오는 중...' : '이름, 계정, 조직으로 검색...'} disabled={loadingUsers} - className="w-full max-w-sm px-3 py-2 text-xs bg-bg-elevated border border-stroke rounded-md text-fg placeholder-fg-disabled focus:border-color-accent focus:outline-none font-korean disabled:opacity-50" + className="w-full max-w-sm px-3 py-2 text-caption bg-bg-elevated border border-stroke rounded-md text-fg placeholder-fg-disabled focus:border-color-accent focus:outline-none font-korean disabled:opacity-50" /> {showDropdown && filteredUsers.length > 0 && (
@@ -826,7 +826,7 @@ function UserPermTab({ roles, permTree, rolePerms }: UserPermTabProps) { className="w-full px-3 py-2 text-left hover:bg-bg-surface-hover transition-colors flex items-center gap-2" >
-
+
{user.name} {user.rank && ( @@ -848,7 +848,7 @@ function UserPermTab({ roles, permTree, rolePerms }: UserPermTabProps) {
)} {showDropdown && !loadingUsers && filteredUsers.length === 0 && searchQuery && ( -
+
검색 결과 없음
)} @@ -954,13 +954,13 @@ function UserPermTab({ roles, permTree, rolePerms }: UserPermTabProps) {
) : ( -
+
역할을 하나 이상 할당하면 유효 권한이 표시됩니다
)} ) : ( -
+
사용자를 선택하세요
)} @@ -1180,7 +1180,7 @@ function PermissionsPanel() { if (loading) { return ( -
+
불러오는 중...
); @@ -1194,7 +1194,7 @@ function PermissionsPanel() { style={{ flexShrink: 0 }} >
-

권한 관리

+

권한 관리

역할별 리소스 × CRUD 권한 설정

@@ -1203,7 +1203,7 @@ function PermissionsPanel() {
@@ -168,7 +168,7 @@ const SensitiveLayerPanel = ({ categoryCode, title }: SensitiveLayerPanelProps) {/* 오류 메시지 */} {error && ( -
+
{error}
)} @@ -176,7 +176,7 @@ const SensitiveLayerPanel = ({ categoryCode, title }: SensitiveLayerPanelProps) {/* 테이블 영역 */}
{loading ? ( -
+
불러오는 중...
) : ( @@ -217,7 +217,7 @@ const SensitiveLayerPanel = ({ categoryCode, title }: SensitiveLayerPanelProps) 데이터가 없습니다. @@ -228,12 +228,12 @@ const SensitiveLayerPanel = ({ categoryCode, title }: SensitiveLayerPanelProps) key={item.layerCd} className="border-b border-stroke hover:bg-[rgba(255,255,255,0.02)] transition-colors" > - + {(page - 1) * PAGE_SIZE + idx + 1} {item.layerCd} - {item.layerNm} - + {item.layerNm} + {item.layerFullNm} @@ -246,7 +246,7 @@ const SensitiveLayerPanel = ({ categoryCode, title }: SensitiveLayerPanelProps) {item.wmsLayerNm ?? -} - + {item.sortOrd} diff --git a/frontend/src/tabs/admin/components/SettingsPanel.tsx b/frontend/src/tabs/admin/components/SettingsPanel.tsx index bd09b68..36e8923 100644 --- a/frontend/src/tabs/admin/components/SettingsPanel.tsx +++ b/frontend/src/tabs/admin/components/SettingsPanel.tsx @@ -54,7 +54,7 @@ function SettingsPanel() { if (loading) { return ( -
+
불러오는 중...
); @@ -64,7 +64,7 @@ function SettingsPanel() {

시스템 설정

-

+

사용자 등록 및 권한 관련 시스템 설정을 관리합니다

@@ -74,7 +74,7 @@ function SettingsPanel() { {/* 사용자 등록 설정 */}
-

사용자 등록 설정

+

사용자 등록 설정

신규 사용자 등록 시 적용되는 정책을 설정합니다

@@ -140,7 +140,7 @@ function SettingsPanel() { {/* OAuth 설정 */}
-

Google OAuth 설정

+

Google OAuth 설정

Google 계정 로그인 시 자동 승인할 이메일 도메인을 설정합니다

@@ -162,7 +162,7 @@ function SettingsPanel() { value={oauthDomainInput} onChange={(e) => setOauthDomainInput(e.target.value)} placeholder="gcsc.co.kr, example.com" - className="flex-1 px-3 py-2 text-xs bg-bg-elevated border border-stroke rounded-md text-fg placeholder-fg-disabled focus:border-color-accent focus:outline-none font-mono" + className="flex-1 px-3 py-2 text-caption bg-bg-elevated border border-stroke rounded-md text-fg placeholder-fg-disabled focus:border-color-accent focus:outline-none font-mono" /> - + {idx + 1} {isEditing ? ( @@ -152,14 +152,14 @@ function SortableMenuItem({ diff --git a/frontend/src/tabs/admin/components/UsersPanel.tsx b/frontend/src/tabs/admin/components/UsersPanel.tsx index a3bb490..5a57d34 100644 --- a/frontend/src/tabs/admin/components/UsersPanel.tsx +++ b/frontend/src/tabs/admin/components/UsersPanel.tsx @@ -87,7 +87,7 @@ function RegisterModal({ allRoles, allOrgs, onClose, onSuccess }: RegisterModalP
{/* 헤더 */}
-

사용자 등록

+

사용자 등록

@@ -129,7 +129,7 @@ function RegisterModal({ allRoles, allOrgs, onClose, onSuccess }: RegisterModalP value={password} onChange={(e) => setPassword(e.target.value)} placeholder="초기 비밀번호" - className="w-full px-3 py-2 text-xs bg-bg-elevated border border-stroke rounded-md text-fg placeholder-fg-disabled focus:border-color-accent focus:outline-none font-mono" + className="w-full px-3 py-2 text-caption bg-bg-elevated border border-stroke rounded-md text-fg placeholder-fg-disabled focus:border-color-accent focus:outline-none font-mono" />
@@ -143,7 +143,7 @@ function RegisterModal({ allRoles, allOrgs, onClose, onSuccess }: RegisterModalP value={name} onChange={(e) => setName(e.target.value)} placeholder="실명" - className="w-full px-3 py-2 text-xs bg-bg-elevated border border-stroke rounded-md text-fg placeholder-fg-disabled focus:border-color-accent focus:outline-none font-korean" + className="w-full px-3 py-2 text-caption bg-bg-elevated border border-stroke rounded-md text-fg placeholder-fg-disabled focus:border-color-accent focus:outline-none font-korean" />
@@ -157,7 +157,7 @@ function RegisterModal({ allRoles, allOrgs, onClose, onSuccess }: RegisterModalP value={rank} onChange={(e) => setRank(e.target.value)} placeholder="예: 팀장, 주임 등" - className="w-full px-3 py-2 text-xs bg-bg-elevated border border-stroke rounded-md text-fg placeholder-fg-disabled focus:border-color-accent focus:outline-none font-korean" + className="w-full px-3 py-2 text-caption bg-bg-elevated border border-stroke rounded-md text-fg placeholder-fg-disabled focus:border-color-accent focus:outline-none font-korean" />
@@ -169,7 +169,7 @@ function RegisterModal({ allRoles, allOrgs, onClose, onSuccess }: RegisterModalP setOrgSn(e.target.value !== '' ? Number(e.target.value) : '')} - className="w-full px-3 py-1.5 text-xs bg-bg-elevated border border-stroke rounded-md text-fg focus:border-color-accent focus:outline-none font-korean" + className="w-full px-3 py-1.5 text-caption bg-bg-elevated border border-stroke rounded-md text-fg focus:border-color-accent focus:outline-none font-korean" > {allOrgs.map((org) => ( @@ -427,7 +427,7 @@ function UserDetailModal({ user, allOrgs, onClose, onUpdated }: UserDetailModalP value={newPassword} onChange={(e) => setNewPassword(e.target.value)} placeholder="새 비밀번호 입력" - className="w-full px-3 py-1.5 text-xs bg-bg-elevated border border-stroke rounded-md text-fg placeholder-fg-disabled focus:border-color-accent focus:outline-none font-mono" + className="w-full px-3 py-1.5 text-caption bg-bg-elevated border border-stroke rounded-md text-fg placeholder-fg-disabled focus:border-color-accent focus:outline-none font-mono" />
@@ -680,7 +680,7 @@ function UsersPanel() {

사용자 관리

-

+

총 {filteredUsers.length}명

@@ -698,7 +698,7 @@ function UsersPanel() { setOrgFilter(e.target.value); setCurrentPage(1); }} - className="px-3 py-2 text-xs bg-bg-elevated border border-stroke rounded-md text-fg focus:border-color-accent focus:outline-none font-korean" + className="px-3 py-2 text-caption bg-bg-elevated border border-stroke rounded-md text-fg focus:border-color-accent focus:outline-none font-korean" > {allOrgs.map((org) => ( @@ -711,7 +711,7 @@ function UsersPanel() { @@ -110,7 +110,7 @@ function VesselMaterialsPanel() { setDate(e.target.value)} - className="px-2 py-1 text-xs rounded bg-bg-elevated border border-stroke-1 text-fg" + className="px-2 py-1 text-caption rounded bg-bg-elevated border border-stroke-1 text-fg" /> @@ -163,7 +163,7 @@ export default function VesselSignalPanel() {
{loading ? (
- 로딩 중... + 로딩 중...
) : (
diff --git a/frontend/src/tabs/aerial/components/CctvView.tsx b/frontend/src/tabs/aerial/components/CctvView.tsx index 93ec81e..1cb1474 100644 --- a/frontend/src/tabs/aerial/components/CctvView.tsx +++ b/frontend/src/tabs/aerial/components/CctvView.tsx @@ -589,7 +589,7 @@ export function CctvView() { {/* 헤더 */}
-
+
-
+
{selectedCamera ? `📹 ${selectedCamera.cameraNm}` : '📹 카메라를 선택하세요'}
{selectedCamera?.sttsCd === 'LIVE' && ( @@ -966,7 +966,7 @@ export function CctvView() {
{/* 출처 헤더 */}
- {group.icon} + {group.icon} {group.label} diff --git a/frontend/src/tabs/aerial/components/MediaManagement.tsx b/frontend/src/tabs/aerial/components/MediaManagement.tsx index 1fa4469..b5f281c 100644 --- a/frontend/src/tabs/aerial/components/MediaManagement.tsx +++ b/frontend/src/tabs/aerial/components/MediaManagement.tsx @@ -421,7 +421,7 @@ export function MediaManagement() {
📥
-
다운로드 완료
+
다운로드 완료
{downloadResult.total}건 선택
@@ -441,7 +441,7 @@ export function MediaManagement() {
@@ -475,7 +475,7 @@ export function MediaManagement() {
-
-
-