From 204114b769a8404b9884676ae11ae79a98c5144c Mon Sep 17 00:00:00 2001 From: Documentation Bot Date: Tue, 17 Mar 2026 06:31:24 +0000 Subject: [PATCH] docs: Sync documentation from private repository --- FRONTEND_DESIGN_PATTERNS.md | 219 ++++++++++++++++++++++++++++++++++++ PROJECT_STRUCTURE.md | 13 ++- ROADMAP.md | 16 +-- 3 files changed, 238 insertions(+), 10 deletions(-) create mode 100644 FRONTEND_DESIGN_PATTERNS.md diff --git a/FRONTEND_DESIGN_PATTERNS.md b/FRONTEND_DESIGN_PATTERNS.md new file mode 100644 index 0000000..dfed7e7 --- /dev/null +++ b/FRONTEND_DESIGN_PATTERNS.md @@ -0,0 +1,219 @@ +# Frontend Design Patterns + +라온누리 프로젝트의 프론트엔드 디자인 패턴 가이드입니다. +`STYLE_GUIDE.md`(컬러, 아이콘, 테마 규칙)와 함께, **어떻게 느끼게 할 것인가**를 정의합니다. + +--- + +## 1. 원칙 + +### 콘텐츠가 주인공이다 + +UI 크롬(타이틀 바, 보더, 패딩)은 최소화한다. +미디어 중심 UI(카메라, 이미지 뷰어, 크로퍼)는 풀블리드로, 컨트롤은 콘텐츠 위에 오버레이한다. +폼/설정 같은 도구 UI에서만 일반 크롬을 유지한다. + +### 상태는 뚝 바뀌지 않는다 + +조건부 렌더링(`{ready && }`)은 레이아웃이 변하는 경우에만 쓴다. +그 외에는 `opacity + transition`으로 부드럽게 드러낸다. + +```tsx +// ✅ opacity 전환 + + +// ❌ 갑자기 나타남 +{ready && } +``` + +### 아이콘은 맥락에 맞게 + +로딩/에러 상태에 제네릭 Spinner 대신, 해당 기능의 아이콘을 사용한다. +카메라 로딩엔 `LuCamera`, 업로드 로딩엔 `LuUpload`, 에러엔 해당 아이콘의 Off 변형(`LuCameraOff`). + +### 비슷한 아이콘은 나란히 두지 않는다 + +같은 도구 모음 안에서 시각적으로 유사한 아이콘이 인접하면 혼란을 준다. +의미가 다른 아이콘이 비슷하게 보이면 아이콘 자체를 바꾼다. + +``` +✅ 회전 LuRotateCw | 초기화 LuUndo2 — 형태가 다름 +❌ 회전 LuRotateCw | 초기화 LuRefreshCw — 둘 다 회전 화살표 +``` + +--- + +## 2. 애니메이션 + +모든 애니메이션은 CSS `@keyframes` + Chakra `css` prop으로 구현한다. + +### 수치 기준 + +| 용도 | duration | easing | +|------|----------|--------| +| 등장 (fadeIn) | 0.3s | ease-out | +| 호버 전환 | 0.2s | — | +| 상태 전환 (색상, 크기) | 0.3s | — | +| 오버레이 reveal | 0.4s | ease | +| 호흡 (pulse) | 2s | ease-in-out | + +### 등장 — scale + fade + +상태 변화(에러/성공/새 요소)에 사용. 0.3초, 살짝 작게 시작. + +```tsx +css={{ + animation: "fadeIn 0.3s ease-out", + "@keyframes fadeIn": { + from: {opacity: 0, transform: "scale(0.9)"}, + to: {opacity: 1, transform: "scale(1)"}, + }, +}} +``` + +순차 등장이 필요하면 `animation-delay`를 `0.1s` 간격으로 준다. + +### 호흡 — 준비 상태 표현 + +"사용 가능"을 은은하게 알린다. 2초 주기, 미세한 변화. + +```tsx +// boxShadow 펄스 (버튼 주변 링) +"@keyframes pulse": { + "0%, 100%": {boxShadow: "0 0 0 0px {colors.brand.solid/30}"}, + "50%": {boxShadow: "0 0 0 6px {colors.brand.solid/0}"}, +} + +// opacity + scale (아이콘) +"@keyframes pulse": { + "0%, 100%": {opacity: 0.4, transform: "scale(1)"}, + "50%": {opacity: 1, transform: "scale(1.1)"}, +} +``` + +### 촉각 피드백 + +모든 커스텀 버튼(`Box as="button"`)에 적용한다. + +```tsx +css={{ + "&:hover": { /* 배경/테두리 변화 */ }, + "&:active": { transform: "scale(0.9)" }, // 눌림 느낌 +}} +transition="all 0.2s" +``` + +### keyframe 네이밍 + +`{컴포넌트}{동작}` camelCase. 범용은 접두사 없이. +예: `cameraPulse`, `shutterReady`, `fadeIn` + +--- + +## 3. 컴포넌트 패턴 + +### Frosted Glass Pill + +미디어 위에 텍스트를 올릴 때 사용. 반투명 배경 + 블러. + +```tsx + +``` + +### 플로팅 툴바 + +미디어 위 도구 버튼을 frosted glass bar로 그룹화. 아이콘 전용, `title`로 레이블. +**성격이 다른 도구 그룹 사이에는 세로 디바이더**를 넣는다. + +```tsx + + {/* 편집 도구 */} + } /> + } /> + } /> + {/* 디바이더 — 파괴적 도구 분리 */} + + } /> + +``` + +ToolButton 스펙: `w={9} h={9}`, `borderRadius="full"`, hover `rgba(255,255,255,0.2)`, active `scale(0.9)` + +### 은은한 글로우 + +어두운 배경 위 흰색 요소에 빛 번짐. `boxShadow="0 0 6px rgba(255,255,255,0.4)"` + +### 안정적 비율 유지 + +비동기 콘텐츠(카메라, 이미지 로딩)는 `aspectRatio`를 고정해 레이아웃 시프트를 방지한다. + +```tsx + + +``` + +### 절대 위치 3단 레이아웃 + +컨트롤 바에서 좌/중앙/우 배치. 중앙은 자연 중앙, 좌우는 `position: absolute`. + +```tsx + + {/* 보조 버튼 */} + {/* 주요 버튼 — 항상 정중앙 */} + {/* 균형 */} + +``` + +--- + +## 4. 상태 표현 + +### 색상으로 구분 + +| 상태 | 색상 | cursor | +|------|------|--------| +| 비활성/로딩 | `border.muted` | `not-allowed` | +| 활성/준비 | `brand.solid` | `pointer` | +| 에러 | `red.subtle` / `red.fg` | — | + +비활성 → 활성 전환에 `transition: "all 0.3s"`를 적용한다. + +### 에러 상태 + +관련 아이콘을 `subtle` 배경 원 안에 배치 + fadeIn 등장. 아래에 설명 텍스트. + +```tsx + + + + + + {errorMessage} + + +``` + +--- + +## 5. 체크리스트 + +새 컴포넌트를 만들 때: + +- [ ] 비동기 콘텐츠 영역에 `aspectRatio` 고정했는가? +- [ ] 로딩/에러 상태에 맥락 부합 아이콘을 사용했는가? +- [ ] 커스텀 버튼에 hover 전환 + active `scale(0.9)` 피드백이 있는가? +- [ ] 상태 전환에 `transition` 또는 `animation`을 적용했는가? +- [ ] 미디어 위 텍스트에 frosted glass pill을 사용했는가? +- [ ] 도구 모음에서 성격이 다른 그룹을 디바이더로 분리했는가? +- [ ] 인접 아이콘이 시각적으로 혼동되지 않는가? + +--- + +© 2024 BlueNovaLab. All rights reserved. diff --git a/PROJECT_STRUCTURE.md b/PROJECT_STRUCTURE.md index 35ff0d4..620d98b 100644 --- a/PROJECT_STRUCTURE.md +++ b/PROJECT_STRUCTURE.md @@ -1,10 +1,17 @@ # 라온누리 - 프로젝트 구조 -> 최종 업데이트: 2025-12-23 (이미지 4:3 비율 표준화) +> 최종 업데이트: 2026-03-09 (글쓰기 플로우 단순화) 초등학생을 위한 창작 글쓰기 교육 플랫폼 -**최신 업데이트** (2025-12-23): +**최신 업데이트** (2026-03-09): +- **글쓰기 플로우 단순화** - 학생의 글쓰기 도달 경로를 최대 2클릭으로 단축 + - **`/write` 자동 리다이렉트**: 커리큘럼 파라미터(`topicId`, `startType`, `helpLevel`, `teamId`)를 감지하여 적절한 에디터 페이지로 자동 이동 + - **`NextAssignmentCard`** (`src/components/home/NextAssignmentCard.tsx`): 홈 페이지에 다음 과제 카드 표시, 커리큘럼 진행 상황 기반 + - **`WritingModeSelector` 단순화**: 2단계(시작 타입 → 도움 레벨) → 1단계(토글 + 카드 선택)로 변경 + - **`TopicSelector` 인라인 변형**: `variant="inline"` prop 추가, 에디터 페이지에서 다이얼로그 대신 접이식 패널로 주제 선택 + +**업데이트** (2025-12-23): - 🖼️ **이미지 4:3 비율 표준화** - **AI 이미지 생성**: 16:9 → 4:3 비율 변경 (일관된 이미지 크기) - **ImageCropper 컴포넌트**: react-cropper 기반 이미지 크롭 기능 (4:3 고정) @@ -540,7 +547,7 @@ |-------|------|------|------| | **학습하기** | `/[locale]/learn` | 레슨/코스 학습 | ❌ 미구현 (Navbar 링크만 존재) | | **스티커** | `/[locale]/stickers` | 스티커 컬렉션 | ❌ 미구현 (Navbar 링크만 존재) | -| **마이페이지** | Dialog (별도 페이지 없음) | 사용자 대시보드 다이얼로그 | 🔜 계획 중 (UserProfileButton에서 열림) | +| **마이페이지** | `/[locale]/my` | 사용자 허브 (프로필, 통계, 미리보기, 설정) | ✅ 완료 | --- diff --git a/ROADMAP.md b/ROADMAP.md index 2c1928a..73a0728 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -1,6 +1,6 @@ # 라온누리 - 개발 로드맵 -> 최종 업데이트: 2025-12-24 (인터랙션 페이지 UX 개선) +> 최종 업데이트: 2026-03-09 (글쓰기 플로우 단순화) 초등학생을 위한 창작 글쓰기 교육 플랫폼 개발 계획 @@ -161,6 +161,7 @@ | **AI 이미지 생성 에러 처리 개선** | **에러 코드별 토스트 메시지 처리 로직 개선, plan_not_supported/limit_exceeded/ai_disabled 등 에러 코드 메시지 추가, 에러 발생 시 'selecting' 단계로 되돌아가는 로직 유지, 다국어 지원 (ko/en/ja)** | **2025-12-19** | | **의존성 업데이트** | **@ark-ui/react 및 @zag-js 패키지 버전 업데이트 (v1.29.1 → v1.31.1)** | **2025-12-19** | | **인터랙션 페이지 UX 대폭 개선** | **7:3 그리드 레이아웃 (이미지 70%, 컨트롤러 30%), 한 화면에서 이미지 보면서 편집 가능, 컨트롤러 내부 스크롤 (커스텀 스크롤바), InteractionHeader 컴포넌트 (IntersectionObserver + Sentinel 패턴, sticky header, glassmorphism 효과, 제목 크기 동적 변경 2xl→xl, 버튼 텍스트 숨김), framer-motion 애니메이션 (AnimatePresence, MotionBox/MotionVStack, 모드 전환/영역 선택 부드러운 전환, 0.2~0.3초 ease curve), 영역 목록을 일반 모드에서도 표시 (CustomAreaList, 고급 모드에서만 CustomParameterPanel), 에디터 버튼 우측 패널 상단 이동 (추가/삭제/숨기기, 가로 배치 flex:1), Container maxW 확장 (1400px→95vw), 이미지 반응형 수정 (InteractiveImageViewer width:100%, VStack maxH 제거, aspectRatio 충돌 해결), 높이 제한 80dvh (우측만 스크롤), 타입 체크 통과** | **2025-12-24** | +| **글쓰기 플로우 단순화** | **/write 커리큘럼 파라미터 자동 리다이렉트, NextAssignmentCard (홈 다음 과제 카드), WritingModeSelector 2단계→1단계 단순화 (토글+카드), TopicSelector 인라인 변형 (variant="inline"), 전체 에디터 페이지 topicId searchParam 처리, 다국어 지원 (ko/en/ja)** | **2026-03-09** | | **ImageDropzone 범용화** | **ImageDropzone을 범용 이미지 업로드 컴포넌트로 리팩토링, TeamCoverImageUploader 삭제 및 통합, 새 props 추가 (currentImageUrl, onDelete, containerAspectRatio, acceptedTypes, maxFileSize, labels, showHoverOverlay, label, helperText), document.getElementById→useRef 전환, 팀 생성/공개설정/보안설정 3곳 마이그레이션, 기존 글쓰기 5곳은 변경 없음 (모든 새 props optional + 기본값 동일)** | **2026-02-26** | | **ImageDropzone 카메라 촬영 기능** | **CameraCaptureDialog 컴포넌트 신규 생성 (GlassDialog 기반, getUserMedia 카메라 스트림, 4:3 프레임 가이드 오버레이, 전/후면 카메라 전환), ImageDropzone에 "카메라로 촬영" 버튼 추가 (파일 선택과 나란히 배치), 촬영 → ImageCropper 크롭 플로우 연동, 카메라 권한 거부/미지원 에러 처리, 다국어 지원 (camera namespace ko/en/ja 7개 키), 모든 사용처(글쓰기 5곳, 팀 3곳) 자동 활성화** | **2026-03-03** | @@ -244,11 +245,12 @@ | 항목 | 설명 | 우선순위 | |-----|------|---------| -| **ProfileDialog (마이페이지)** | **Dialog 형식 대시보드 (탭 기반)** | 🔴 높음 | -| ├─ 내정보 탭 | 프로필 정보, 레벨, XP 표시 | 🔴 높음 | -| ├─ 내글 탭 | 작성한 글 목록 (페이지네이션) | 🔴 높음 | -| ├─ 통계 탭 | 글 수, 레벨, 스티커 통계 차트 | 🟡 중간 | -| └─ 설정 탭 | 프로필 편집, 비밀번호 변경, 계정 설정 | 🟡 중간 | +| **~~ProfileDialog~~ 마이페이지 (`/my`)** | **허브형 페이지로 구현 완료** | ✅ 완료 | +| ├─ 프로필 히어로 | 아바타 (사진 업로드), 이름 인라인 편집, 플랜 뱃지 | ✅ 완료 | +| ├─ 통계 카드 | 작성 글 수, 팀 수, AI 크레딧, 주간 목표 | ✅ 완료 | +| ├─ 미리보기 섹션 | 내 글/팀/학습과정 최근 3개 + "모두 보기" 링크 | ✅ 완료 | +| ├─ 환경 설정 | 테마 토글 (즉시 적용), 주간 목표 슬라이더 (디바운스 자동저장) | ✅ 완료 | +| └─ 계정 섹션 | 구독 정보, AI 사용량, 계정 삭제 | ✅ 완료 | | 글 검색 | 제목/내용 기반 검색 | 🟡 중간 | | 알림 시스템 | 인앱 알림 (스티커, 레벨업) | 🟢 낮음 | | 알림 센터 | 알림 목록 및 설정 | 🟢 낮음 | @@ -353,7 +355,7 @@ enum UserRole { - 스티커 컬렉션 ### M4: 베타 출시 (2026년 3월 15일) -- ProfileDialog (마이페이지) 및 통계 +- ~~ProfileDialog (마이페이지)~~ → `/my` 허브 페이지로 완료 - 알림 시스템 ### M5: 정식 출시 (2026년 5월 31일)