feat(frontend): 디자인 시스템 SSOT 확립 + 전체 페이지 마이그레이션 + a11y 전수 처리 #18
No reviewers
레이블
레이블 없음
마일스톤 없음
담당자 없음
참여자 2명
알림
마감일
마감일이 설정되지 않았습니다.
의존성
No dependencies set.
Reference: gc/kcg-ai-monitoring#18
불러오는 중...
Reference in New Issue
Block a user
No description provided.
Delete Branch "feature/design-system-showcase"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
개요
프론트엔드 UI를
/design-system.html쇼케이스 기반 단일 진실 공급원(SSOT) 구조로 재정비. 35+ feature 페이지 마이그레이션 + WCAG 2.1 Level A 접근성 전수 처리.Phase A — 디자인 쇼케이스 페이지
/design-system.html별도 Vite entry (메인 SPA와 분리, 54KB)TRK-<카테고리>-<슬러그>(호버 툴팁, 클립보드 복사, 해시 딥링크)A로 다크/라이트 토글Phase B — 신규 공통 컴포넌트
Button(5 variant × 3 size = 15)Input/Select/Textarea/Checkbox/RadioTabBar/TabButton(underline / pill / segmented)PageContainer(size sm/md/lg + fullBleed)PageHeader(icon + title + description + demo + actions)Section(Card 단축)Phase C — SSOT 구조화
catalogRegistry.ts— 23개 카탈로그 통합 (자동 enumerate)variantMeta.ts— Badge intent 8종 + Button variant 5종 의미 가이드statusIntent.ts— ad-hoc 상태 → BadgeIntent + getRiskIntent(0~100)Phase D — 35+ 페이지 마이그레이션
-m-4해킹 →<PageContainer fullBleed>Phase E — 위반 전수 제거
bg-X-500/20 text-X-400: 56 → 0<button>type 누락: 86 → 0Phase F — Badge 테마 분리
bg-X-100 text-X-900 border-X-300(파스텔)dark:bg-X-500/20 dark:text-X-400 dark:border-X-500/30(translucent)Phase G — 접근성 (WCAG 2.1 Level A)
Select컴포넌트 TypeScript union으로aria-label/aria-labelledby/title컴파일 강제<select>5곳 aria-label<button>16곳 aria-label<input>/<textarea>28곳 aria-labelrole="switch"+aria-checkedPhase H — 호환성
backdrop-filter-webkit-prefix 추가 (DesignSystemApp.css)trk-pulsekeyframe outline-color → opacity (composite-only 최적화)CLAUDE.md 개발 지침
변경 통계
검증
관련
변경: - badgeVariants 8 intent 모두 라이트/다크 팔레트 분리 - 다크: 밝은 솔리드 배경(-400) + slate-900 글자 + 강한 보더(-600) - 라이트: 파스텔 배경(-100) + 진한 글자(-900) + 소프트 보더(-300) - base에서 text-on-bright 제거 (intent별로 관리) - classes 기반 카탈로그 4종에 dark: 변형 추가로 라이트 모드 대응: - eventStatuses: bg-red-100 text-red-800 dark:bg-red-500/20 dark:text-red-400 - enforcementResults: 동일 패턴 (red/purple/yellow/green) - patrolStatuses: border 포함 (7 상태) - enforcementActions: classes 필드 신규 추가 (기존에 없어서 fallback grey로 떨어져 라이트 모드에서 글자 안 보이던 원인) - CatalogSection fallback classes도 dark: 변형 추가 (안전장치) - enforcementActions에 getEnforcementActionClasses() 헬퍼 신규 빌드 검증: - tsc ✅, vite build ✅ - CSS 확인: .dark\:bg-red-400:is(.dark *) 컴파일 정상Phase A: 쇼케이스의 카탈로그/variant 정보를 중앙 상수로 끌어올림 - shared/constants/catalogRegistry.ts 신규 - 19+ 카탈로그의 id/showcaseId/titleKo/titleEn/description/source/items를 단일 레지스트리로 통합 관리 - 새 카탈로그 추가 = 레지스트리에 1줄 추가로 쇼케이스 자동 노출 - CATALOG_REGISTRY + getCatalogById() - lib/theme/variantMeta.ts 신규 - BADGE_INTENT_META: 8 intent의 titleKo/titleEn/description - BUTTON_VARIANT_META: 5 variant의 titleKo/titleEn/description - BADGE_INTENT_ORDER/SIZE_ORDER, BUTTON_VARIANT_ORDER/SIZE_ORDER - 쇼케이스 섹션 리팩토링 — 하드코딩 제거 - CatalogSection: CATALOG_REGISTRY 자동 열거 (CATALOGS 배열 삭제) - BadgeSection: BADGE_INTENT_META에서 의미 가이드 + titleKo 참조 - ButtonSection: BUTTON_VARIANT_META에서 의미 가이드 + titleKo 참조 효과: - 카탈로그의 라벨/색상/intent 변경 시 쇼케이스와 실 페이지 동시 반영 - Badge/Button의 variant 의미가 variantMeta 한 곳에서 관리됨 - 쇼케이스 섹션에 분산돼 있던 하드코딩 제거 (INTENT_USAGE, VARIANT_USAGE 등) 다음 단계: 실 페이지를 PageContainer/PageHeader/Button/Input으로 마이그레이션Phase C-2 (인라인 <button>): - TabBar/TabButton 공통 컴포넌트 신규 (underline/pill/segmented 3종) - DataHub: 메인 탭 → TabBar + TabButton 전환, 필터 pill 전환, CTA 버튼 (작업 등록/스토리지 관리/새로고침) → Button variant - PermissionsPanel: 역할 생성/저장 → Button variant, icon 버튼 유지 - Python 일괄 치환: 51개 inline <button>에 type="button" 추가 - 남은 <button> type 누락 0건 (multi-line 포함) Phase C-3 (하드코딩 색상): - AdminPanel SERVER_STATUS 뱃지: getStatusIntent() 사용으로 통일 - bg-X-500/20 text-X-400 패턴 0건 Phase C-4 (인라인 style): - LiveMapView BaseMap minHeight → className="min-h-[400px]" - 나머지 89건 style={{}}은 모두 dynamic value (progress width, toggle left, 데이터 기반 color 등)로 정당함 4개 catalog (eventStatuses/enforcementResults/enforcementActions/ patrolStatuses)에 intent 필드 추가, statusIntent.ts 공통 유틸 신규. 이제 모든 Badge가 쇼케이스 팔레트 자동 적용됨. 빌드 검증: - tsc ✅, eslint ✅, vite build ✅ - 남은 위반 지표: Badge className 0, button-type-missing 0, 하드코딩 색상 0axe/forms/backdrop 에러 3종 모두 해결: 1) CSS: backdrop-filter Safari 호환성 - design-system CSS에 -webkit-backdrop-filter 추가 - trk-pulse 애니메이션을 outline-color → opacity로 변경 (composite만 트리거, paint/layout 없음 → 더 나은 성능) 2) 아이콘 전용 <button> aria-label 추가 (9곳): - MainLayout 알림 버튼 → '알림' - UserRoleAssignDialog 닫기 → '닫기' - AIAssistant/MLOpsPage 전송 → '전송' - ChinaFishing 좌/우 네비 → '이전'/'다음' - 공통 컴포넌트 (PrintButton/ExcelExport/SaveButton) type=button 누락 보정 3) <input>/<textarea> 접근 이름 27곳 추가: - 로그인 폼, ParentReview/LabelSession/ParentExclusion 폼 (10) - NoticeManagement 제목/내용/시작일/종료일 (4) - SystemConfig/DataHub/PermissionsPanel 검색·역할 입력 (5) - VesselDetail 조회 시작/종료/MMSI (3) - GearIdentification InputField에 label prop 추가 - AIAssistant/MLOpsPage 질의 input/textarea - MainLayout 페이지 내 검색 - 공통 placeholder → aria-label 자동 복제 (3) Button 컴포넌트에는 접근성 정책 JSDoc 명시 (타입 강제는 API 복잡도 대비 이득 낮아 문서 가이드 + 코드 리뷰로 대응). 검증: - 실제 위반 지표: inaccessible button 0, inaccessible input 0, textarea 0 - tsc ✅, eslint ✅, vite build ✅ - dist CSS에 -webkit-backdrop-filter 확인됨이전 스캐너가 놓친 패턴 — 모달 닫기 X 버튼과 토글 스위치 등: - NoticeManagement: 모달 헤더 X → '닫기' - ReportManagement: 업로드 패널 X → '업로드 패널 닫기' - AIModelManagement: 규칙 토글 → role=switch + aria-checked + aria-label API 예시 복사 → '예시 URL 복사' - FileUpload: 파일 제거 X → '{파일명} 제거' - NotificationBanner: 알림 닫기 X → '알림 닫기' - SearchInput: 입력 aria-label (placeholder), 지우기 버튼 → '검색어 지우기' 검증: - 개선된 스캐너로 remaining=0 확인 (JSX tag 중첩 파싱) - tsc ✅디자인 시스템 SSOT + 전체 페이지 마이그레이션 + WCAG 2.1 a11y 전수 처리 승인 (via /mr skill)