265 lines
7.6 KiB
Markdown
265 lines
7.6 KiB
Markdown
# Style Guide
|
|
|
|
라온누리 프로젝트의 코딩 스타일 가이드입니다.
|
|
|
|
---
|
|
|
|
## Color Usage Guidelines
|
|
|
|
### 핵심 원칙
|
|
|
|
**항상 브랜드 컬러를 우선 사용하세요:**
|
|
|
|
1. **버튼에는 항상 `colorPalette="brand"`** 사용:
|
|
```tsx
|
|
// ✅ Good
|
|
<Button colorPalette="brand">클릭</Button>
|
|
|
|
// ❌ Bad
|
|
<Button>클릭</Button> // 기본 gray 사용 금지
|
|
```
|
|
|
|
2. **Semantic 토큰 우선 사용** (하드코딩된 숫자 금지):
|
|
```tsx
|
|
// ✅ Good
|
|
color="fg" // 기본 텍스트
|
|
color="fg.muted" // 보조 텍스트
|
|
color="brand.fg" // 브랜드 텍스트
|
|
bg="bg" // 기본 배경
|
|
bg="brand.subtle" // 브랜드 배경
|
|
borderColor="border.muted"
|
|
|
|
// ❌ Bad
|
|
color="gray.600" // 숫자 사용 금지
|
|
bg="#FF6B9D" // 하드코딩 금지
|
|
```
|
|
|
|
3. **브랜드 컬러 활용**:
|
|
- Primary actions: `colorPalette="brand"` (핑크)
|
|
- Secondary: `colorPalette="teal"`, `colorPalette="blue"`
|
|
- Destructive: `colorPalette="red"`
|
|
- Success: `colorPalette="green"`
|
|
|
|
4. **다크 모드 대응**:
|
|
- Semantic 토큰 사용 시 자동으로 light/dark 변환
|
|
- ❌ **`useColorModeValue()` 사용 금지** - 전체 프로젝트에서 제거됨 (2025-11-10)
|
|
- ✅ **Semantic token 또는 conditional style 객체 사용**:
|
|
```tsx
|
|
// ✅ Good - Semantic token (단색)
|
|
<Box bg="bg" color="fg" borderColor="border.muted">
|
|
|
|
// ✅ Good - Semantic token (그라데이션은 var() 필수)
|
|
<Box bgGradient="var(--chakra-colors-landing-hero-bg)">
|
|
|
|
// ✅ Good - Conditional style 객체 (특수한 경우에만, 기본적으로는 Semantic token 우선)
|
|
<Box _hover={{bg: {_light: "gray.50", _dark: "gray.700"}}}>
|
|
|
|
// ✅ Good - Conditional style 객체 (그라데이션)
|
|
<Box bgGradient={{
|
|
_light: "linear-gradient(to bottom right, #FFE5E5, #FFF5E5, #E5F5FF)",
|
|
_dark: "linear-gradient(to bottom right, gray.900, gray.800, blue.900)"
|
|
}}>
|
|
|
|
// ❌ Bad - useColorModeValue 사용 금지
|
|
const bg = useColorModeValue("white", "gray.800");
|
|
```
|
|
|
|
### Landing 페이지 전용 토큰
|
|
|
|
```tsx
|
|
color="landing.text" // 메인 텍스트 (#2C3E50 / gray.100)
|
|
color="landing.subtext" // 보조 텍스트 (#5A6C7D / gray.300)
|
|
bg="landing.section.bg" // 섹션 배경 (#F8F9FA / gray.800)
|
|
bg="landing.footer.bg" // Footer 배경
|
|
|
|
// ⚠️ 그라데이션은 var() 사용 필수
|
|
bgGradient="var(--chakra-colors-landing-hero-bg)"
|
|
|
|
// Feature Card 색상 (11가지)
|
|
bg="landing.feature.pink.bg" // 1. Pink (#FFE5EE / #FF6B9D)
|
|
bg="landing.feature.teal.bg" // 2. Teal (#E5F9F7 / #4ECDC4)
|
|
bg="landing.feature.yellow.bg" // 3. Yellow (#FFF9E5 / #FFD93D)
|
|
bg="landing.feature.mint.bg" // 4. Mint (#E5F9F5 / #95E1D3)
|
|
bg="landing.feature.purple.bg" // 5. Purple (#F3E5F5 / #9C27B0)
|
|
bg="landing.feature.blue.bg" // 6. Blue (#E3F2FD / #2196F3)
|
|
bg="landing.feature.orange.bg" // 7. Orange (#FFF3E0 / #FF9800)
|
|
bg="landing.feature.green.bg" // 8. Green (#E8F5E9 / #4CAF50)
|
|
bg="landing.feature.red.bg" // 9. Red (#FFEBEE / #F44336)
|
|
bg="landing.feature.indigo.bg" // 10. Indigo (#E8EAF6 / #3F51B5)
|
|
bg="landing.feature.lime.bg" // 11. Lime (#F9FBE7 / #CDDC39)
|
|
|
|
color="landing.feature.{color}.icon" // 아이콘 색상 (500 shade)
|
|
```
|
|
|
|
---
|
|
|
|
## Icon 사용 규칙
|
|
|
|
**react-icons 필수** (이모티콘 사용 금지):
|
|
|
|
- ✅ `react-icons/lu` (Lucide) - 메인 아이콘 세트
|
|
- ✅ `react-icons/fa` (Font Awesome) - 보조 아이콘
|
|
- ❌ 이모티콘 (🌍📝🔐) - 사용 금지 (브라우저마다 다르게 표시)
|
|
|
|
### 사용 예시
|
|
|
|
```tsx
|
|
import { LuGlobe, LuClipboardList, LuLock } from "react-icons/lu";
|
|
import { FaUserGraduate } from "react-icons/fa";
|
|
|
|
// ✅ Good
|
|
<Icon as={LuGlobe} />
|
|
|
|
// ❌ Bad
|
|
<Text>🌍</Text> // 이모티콘 사용 금지
|
|
```
|
|
|
|
---
|
|
|
|
## Chakra UI 테마 확장
|
|
|
|
### 위치
|
|
- **파일**: `src/theme/system.ts`
|
|
- Semantic tokens, recipes 패턴 따르기
|
|
- **Overlay UI (Dialog, Select, Menu)**: Portal 사용, bg 자동 적용
|
|
|
|
### 테마 슬롯 레시피
|
|
|
|
Dialog, Select 등 Overlay 컴포넌트는 slot recipe 적용:
|
|
|
|
```typescript
|
|
// src/theme/system.ts
|
|
export default createSystem(defaultConfig, {
|
|
theme: {
|
|
recipes: {
|
|
dialog: defineRecipe({
|
|
base: {
|
|
backdrop: {
|
|
backdropFilter: "blur(4px)",
|
|
},
|
|
content: {
|
|
bg: "bg",
|
|
borderColor: "border.muted",
|
|
shadow: "lg",
|
|
},
|
|
},
|
|
}),
|
|
},
|
|
},
|
|
});
|
|
```
|
|
|
|
---
|
|
|
|
## 컴포넌트 스타일 가이드
|
|
|
|
### GlassCard 컴포넌트
|
|
|
|
반투명 배경 + 블러 효과 통일:
|
|
|
|
```tsx
|
|
<GlassCard>
|
|
<CardHeader>제목</CardHeader>
|
|
<CardBody>내용</CardBody>
|
|
</GlassCard>
|
|
```
|
|
|
|
**특징**:
|
|
- 자동 배경 블러 (`backdrop-filter: blur(8px)`)
|
|
- 다크 모드 자동 대응
|
|
- 일관된 시각적 통일성
|
|
|
|
**Props**:
|
|
- `glow`: 호버 시 그라데이션 글로우 효과
|
|
- `isClickable`: 클릭 가능 상태 (커서 변경, 호버 효과)
|
|
|
|
### Glassmorphism Dialog 패턴
|
|
|
|
UserSettingsDialog와 TopicSelector에서 사용하는 고급 glassmorphism 패턴:
|
|
|
|
```tsx
|
|
<Dialog.Root open={open} onOpenChange={onOpenChange} size="xl">
|
|
<Portal>
|
|
<Dialog.Backdrop
|
|
bg="blackAlpha.600"
|
|
backdropFilter="blur(8px)"
|
|
/>
|
|
<Dialog.Positioner>
|
|
<Dialog.Content
|
|
p={0}
|
|
overflow="hidden"
|
|
bg="bg/85"
|
|
backdropFilter="blur(5px)"
|
|
borderWidth="1px"
|
|
borderColor="whiteAlpha.200"
|
|
borderRadius="2em"
|
|
boxShadow="0 8px 32px 0 rgba(0, 0, 0, 0.37)"
|
|
css={{
|
|
background: 'linear-gradient(135deg, rgba(255, 255, 255, 0.1) 0%, rgba(255, 255, 255, 0.05) 100%)',
|
|
'&::before': {
|
|
content: '""',
|
|
position: 'absolute',
|
|
top: 0,
|
|
left: 0,
|
|
width: '400px',
|
|
height: '400px',
|
|
background: 'radial-gradient(circle at top left, rgba(59, 130, 246, 0.3) 0%, rgba(59, 130, 246, 0.15) 25%, transparent 60%)',
|
|
pointerEvents: 'none',
|
|
borderTopLeftRadius: 'inherit',
|
|
zIndex: 0,
|
|
},
|
|
'&::after': {
|
|
content: '""',
|
|
position: 'absolute',
|
|
bottom: 0,
|
|
right: 0,
|
|
width: '400px',
|
|
height: '400px',
|
|
background: 'radial-gradient(circle at bottom right, rgba(255, 107, 157, 0.2) 0%, rgba(255, 107, 157, 0.1) 30%, transparent 70%)',
|
|
pointerEvents: 'none',
|
|
borderBottomRightRadius: 'inherit',
|
|
zIndex: 0,
|
|
}
|
|
}}
|
|
>
|
|
{/* Content with sidebar tabs */}
|
|
</Dialog.Content>
|
|
</Dialog.Positioner>
|
|
</Portal>
|
|
</Dialog.Root>
|
|
```
|
|
|
|
**주요 효과**:
|
|
- **멀티레이어 glassmorphism**: 베이스 그라데이션 + 청색 악센트(좌상단) + 분홍색 악센트(우하단)
|
|
- **Backdrop blur**: 배경 8px 블러 처리
|
|
- **Content blur**: 컨텐츠 5px 블러 + 85% 투명도
|
|
- **Radial gradients**: 대화상자에 깊이감과 프리미엄 느낌 부여
|
|
|
|
**사용 컴포넌트**:
|
|
- `UserSettingsDialog.tsx` - 사용자 설정 (프로필, 환경설정 탭)
|
|
- `TopicSelector.tsx` - 주제 선택 (내 주제 + 팀별 탭, 미리보기 패널)
|
|
|
|
### 버튼 스타일
|
|
|
|
```tsx
|
|
// Primary action
|
|
<Button colorPalette="brand">저장</Button>
|
|
|
|
// Secondary action
|
|
<Button variant="outline" colorPalette="teal">취소</Button>
|
|
|
|
// Destructive action
|
|
<Button colorPalette="red">삭제</Button>
|
|
```
|
|
|
|
---
|
|
|
|
## 관련 문서
|
|
|
|
- chakra mcp
|
|
- [TECH_STACK.md](./TECH_STACK.md) - 기술 스택
|
|
- [CLAUDE.md](./CLAUDE.md) - 개발 가이드
|
|
|
|
---
|
|
|
|
© 2024 BlueNovaLab. All rights reserved. |