generated from gc/template-java-maven
- 디자인 시스템 가이드 문서 11개 생성 (docs/design/) - CSS 변수 토큰 시스템 (@theme + :root/.dark 전환) - cn() 유틸리티 (clsx + tailwind-merge) - Button/Badge 공통 컴포넌트 (variant/size, 다크모드 대응) - 하드코딩 Tailwind 색상 → CSS 변수 토큰 리팩토링 (30개 파일) - 차트 팔레트 다크모드 색상 업데이트 (CHART_COLORS_HEX) - 버튼 다크모드 채도/대비 강화 (primary-600 기반) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
213 lines
4.7 KiB
Markdown
213 lines
4.7 KiB
Markdown
# Do & Don't
|
|
|
|
디자인 시스템 적용 시 자주 발생하는 실수와 올바른 방법.
|
|
|
|
---
|
|
|
|
## CSS 변수 토큰
|
|
|
|
### 색상
|
|
|
|
**DO** — CSS 변수 토큰 사용
|
|
|
|
```tsx
|
|
<div className="bg-[var(--color-bg-surface)] text-[var(--color-text-primary)] border border-[var(--color-border)]" />
|
|
```
|
|
|
|
**DON'T** — HEX 하드코딩
|
|
|
|
```tsx
|
|
// 다크 모드 전환 불가, 토큰 변경 시 전부 수정 필요
|
|
<div className="bg-white text-gray-900 border border-gray-200" />
|
|
```
|
|
|
|
**DON'T** — Tailwind 기본 팔레트로 브랜드 컬러 표현
|
|
|
|
```tsx
|
|
// 브랜드 컬러(#6D94C5)와 blue-500(#3B82F6)은 다른 색상
|
|
<div className="bg-blue-500 text-blue-900" />
|
|
```
|
|
|
|
---
|
|
|
|
## 시멘틱 컬러
|
|
|
|
**DO** — 의미에 맞는 시멘틱 컬러 사용
|
|
|
|
```tsx
|
|
// 성공 상태
|
|
<Badge className="bg-[var(--color-success)]/10 text-[var(--color-success)]">완료</Badge>
|
|
|
|
// 오류 메시지
|
|
<p className="text-[var(--color-danger)] text-sm">{errorMessage}</p>
|
|
|
|
// 경고 알림
|
|
<div className="border-l-4 border-[var(--color-warning)] bg-[var(--color-warning)]/10 p-4" />
|
|
```
|
|
|
|
**DON'T** — 브랜드 컬러를 시멘틱 용도로 사용
|
|
|
|
```tsx
|
|
// Primary 컬러는 성공/오류를 표현하지 않음
|
|
<p className="text-[var(--color-primary)]">저장에 실패했습니다</p>
|
|
```
|
|
|
|
**DON'T** — 시멘틱 컬러를 장식 목적으로 사용
|
|
|
|
```tsx
|
|
// danger 컬러는 위험/오류 상황 전용
|
|
<Badge className="bg-[var(--color-danger)]">인기</Badge>
|
|
```
|
|
|
|
---
|
|
|
|
## Spacing 스케일
|
|
|
|
**DO** — 4px 단위 스케일 사용
|
|
|
|
```tsx
|
|
<div className="p-4 gap-2 mt-6" /> // 16px / 8px / 24px
|
|
<div className="px-3 py-1.5" /> // 12px / 6px (sm 버튼)
|
|
```
|
|
|
|
**DON'T** — 임의의 px 값
|
|
|
|
```tsx
|
|
<div className="p-[13px] gap-[7px] mt-[22px]" />
|
|
```
|
|
|
|
**DON'T** — 인라인 스타일로 여백 지정
|
|
|
|
```tsx
|
|
<div style={{ padding: '13px', marginTop: '22px' }} />
|
|
```
|
|
|
|
---
|
|
|
|
## cn() 유틸리티
|
|
|
|
**DO** — 조건부 클래스에 `cn()` 사용
|
|
|
|
```tsx
|
|
<button
|
|
className={cn(
|
|
'px-4 py-2 rounded-lg font-medium transition-colors',
|
|
isActive ? 'bg-[var(--color-primary)] text-white' : 'text-[var(--color-text-secondary)]',
|
|
disabled && 'opacity-50 cursor-not-allowed',
|
|
className,
|
|
)}
|
|
/>
|
|
```
|
|
|
|
**DON'T** — 템플릿 리터럴로 조건부 클래스 조합
|
|
|
|
```tsx
|
|
// Tailwind 클래스 충돌 가능, purge 미적용 위험
|
|
<button className={`px-4 py-2 ${isActive ? 'bg-blue-500' : ''} ${disabled ? 'opacity-50' : ''}`} />
|
|
```
|
|
|
|
**DON'T** — 동적 클래스 문자열 조합
|
|
|
|
```tsx
|
|
// Tailwind는 전체 클래스 문자열을 스캔 — 동적 조합 시 purge에서 제거될 수 있음
|
|
const color = 'primary';
|
|
<div className={`text-[var(--color-${color})]`} /> // 위험
|
|
```
|
|
|
|
**DO** — 객체 맵 사용
|
|
|
|
```tsx
|
|
const colorMap = {
|
|
primary: 'text-[var(--color-primary)]',
|
|
danger: 'text-[var(--color-danger)]',
|
|
} as const;
|
|
|
|
<div className={cn(colorMap[color])} />
|
|
```
|
|
|
|
---
|
|
|
|
## 컴포넌트 Props
|
|
|
|
**DO** — className prop 허용 + cn() 병합
|
|
|
|
```tsx
|
|
const Card = ({ className, children }: CardProps) => (
|
|
<div className={cn('rounded-xl border border-[var(--color-border)] p-6', className)}>
|
|
{children}
|
|
</div>
|
|
);
|
|
```
|
|
|
|
**DON'T** — className prop 미제공 (재사용성 저하)
|
|
|
|
```tsx
|
|
const Card = ({ children }: { children: React.ReactNode }) => (
|
|
<div className="rounded-xl border border-[var(--color-border)] p-6">
|
|
{children}
|
|
</div>
|
|
);
|
|
```
|
|
|
|
---
|
|
|
|
## 다크 모드
|
|
|
|
**DO** — CSS 변수 토큰 사용으로 자동 전환
|
|
|
|
```tsx
|
|
// --color-bg-surface는 Light: #FFF, Dark: #1E2023으로 자동 전환
|
|
<div className="bg-[var(--color-bg-surface)]" />
|
|
```
|
|
|
|
**DON'T** — `dark:` 클래스로 각각 지정 (토큰이 있는 색상에)
|
|
|
|
```tsx
|
|
// 중복 관리 부담, 토큰과 불일치 가능
|
|
<div className="bg-white dark:bg-gray-900" />
|
|
```
|
|
|
|
단, CSS 변수 토큰이 없는 케이스(투명도, 그라디언트 등)에는 `dark:` 사용 허용.
|
|
|
|
---
|
|
|
|
## 타이포그래피
|
|
|
|
**DO** — 타입 스케일 클래스 사용
|
|
|
|
```tsx
|
|
<h1 className="text-4xl font-bold leading-tight text-[var(--color-text-primary)]">페이지 제목</h1>
|
|
<p className="text-base leading-relaxed text-[var(--color-text-secondary)]">설명 텍스트</p>
|
|
```
|
|
|
|
**DON'T** — 임의 폰트 크기
|
|
|
|
```tsx
|
|
<h1 className="text-[22px] font-bold">페이지 제목</h1>
|
|
```
|
|
|
|
---
|
|
|
|
## 아이콘
|
|
|
|
**DO** — Lucide React + 색상 토큰
|
|
|
|
```tsx
|
|
import { ChevronRight } from 'lucide-react';
|
|
|
|
<ChevronRight className="size-5 text-[var(--color-text-secondary)]" aria-hidden="true" />
|
|
```
|
|
|
|
**DON'T** — 다른 라이브러리 혼용
|
|
|
|
```tsx
|
|
// Font Awesome, Material Icons 등 혼용 금지
|
|
import { FaChevronRight } from 'react-icons/fa';
|
|
```
|
|
|
|
**DON'T** — 아이콘에 color prop으로 HEX 지정
|
|
|
|
```tsx
|
|
<ChevronRight color="#6D94C5" /> // CSS 변수 토큰을 사용할 수 없음
|
|
```
|