Colors
Core
Social / Brand
Glow / Shadow
Typography
Font: Pretendard Variable
Heading 1 — 제목 텍스트 (4xl/bold)
Heading 2 — 제목 텍스트 (3xl/bold)
Heading 3 — 제목 텍스트 (2xl/semibold)
Heading 4 — 제목 텍스트 (xl/semibold)
Heading 5 — 제목 텍스트 (lg/medium)
Body — 본문 텍스트 (base/normal)
Small — 보조 텍스트 (sm/normal)
Caption — 캡션 텍스트 (xs/muted)
Variants
Gradient & Highlight
Sizes
States
Badge
Input & Textarea
Input
Textarea
Select
Radix Select
Card
기본 카드
카드 설명 텍스트
카드 본문 콘텐츠가 여기에 들어가요.
액션 카드
Footer가 있는 카드
버튼이 있는 카드 예시예요.
통계 카드
1,234
총 주문 수
Avatar

Table
| 주문번호 | 상품 | 상태 | 금액 |
|---|---|---|---|
| ORD-001 | N플레이스 트래픽 | 완료 | 50,000원 |
| ORD-002 | 블로그 리뷰 | 진행중 | 120,000원 |
| ORD-003 | 인스타 팔로워 | 취소 | 30,000원 |
Tabs
첫 번째 탭 콘텐츠예요. 개요 정보가 표시돼요.
Dialog
범용 모달 컴포넌트. body scroll lock 내장.hideCloseButton,overlayClassName,closeOnOverlayClick props 지원.
Props: hideCloseButton X 버튼 숨김 | overlayClassName 오버레이 스타일 (예: bg-black/40) | closeOnOverlayClick=false 오버레이 클릭 닫기 비활성화
ConfirmDialog
확인/경고 모달. Dialog 래핑. async onConfirm 시 자동 로딩 상태.import { ConfirmDialog } from '@/components/ui/confirm-dialog'
Props: onConfirm Promise 반환 시 자동 로딩 | confirmVariant "destructive" | "default" | "outline" | loading 외부 로딩 제어
SuccessDialog
성공/완료 모달. 아이콘 + 제목 + 설명 + 액션 버튼. Dialog 래핑.import { SuccessDialog } from '@/components/ui/success-dialog'
Props: icon "success" (녹색) | "warning" (주황) | actions { label, onClick, variant? }[] | children 추가 콘텐츠 삽입 가능
LoadingOverlay
로딩 차단 오버레이. 닫기 불가, 자동 소멸. body scroll lock 내장.import { LoadingOverlay } from '@/components/ui/loading-overlay'
Props: open 표시 여부 | message 메인 메시지 | description 보조 설명 | progressPercent 0~100 진행 바 | footer 하단 추가 콘텐츠
Sheet
Dropdown Menu
Popover
기본 Popover는 padding이 0이에요. 콘텐츠마다 p-3·w-[min(18rem,calc(100vw-2rem))] 등을 명시해야 해요. 간단한 (i) 아이콘 + 설명 패턴은 아래 InfoPopover 사용.
InfoPopover
(i) 아이콘을 누르면 상세 안내가 뜨는 헬퍼예요. padding·모바일 안전 폭·접근성이 미리 적용돼 있어요.import { InfoPopover } from '@/components/ui/info-popover'
Calendar
| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
DatePickerInput
날짜 선택 입력 컴포넌트. Calendar + Popover 조합. YYYY-MM-DD 형식으로 값을 주고받아요.import { DatePickerInput } from '@/components/ui/date-picker-input'
Props: value YYYY-MM-DD | onChange (YYYY-MM-DD) => void | minDate / maxDate 범위 제한 | disabled
Skeleton
Separator
Horizontal
위 영역
아래 영역
Vertical
ScrollArea
오버플로우 스크롤 영역. 긴 콘텐츠를 제한된 높이 안에서 스크롤할 때 사용해요.import { ScrollArea } from '@/components/ui/scroll-area'
className으로 높이 제한. 내부 콘텐츠가 넘치면 자동 스크롤.
ProgressLog
진행 로그 컴포넌트. 실시간 작업 상태를 시각화해요. 새 로그 추가 시 자동 스크롤.import { ProgressLog } from '@/components/ui/progress-log'
Card 래핑 (기본)
키워드 분석 로그
bare 모드 (카드 없이)
Props: logs ProgressLogEntry[] | title 카드 헤더 제목 | maxHeight 최대 높이 (px) | bare 카드 없이 로그만 렌더링
ProgressLogEntry: message + type (info/success/error) + time? + detail? (접이식 상세)
MarkdownContent
마크다운 렌더링 컴포넌트. 파이 AI 응답, 채팅 말풍선 등에서 사용해요.import { MarkdownContent } from '@/components/ui/markdown-content'
렌더링 결과
분석 결과를 알려드릴게요.
현재 등록된 키워드 중 상위 3개 키워드의 순위 변동이에요:
| 키워드 | 현재 순위 | 변동 |
|---|---|---|
| 강남 맛집 | 3위 | +2 |
| 홍대 카페 | 7위 | -1 |
| 성수동 브런치 | 12위 | 신규 |
순위가 상승한 키워드가 있어요. 자세한 내용은 리포트를 확인해주세요.
ranking_score 기반으로 계산됐어요.
원본 마크다운
**분석 결과를 알려드릴게요.** 현재 등록된 키워드 중 상위 3개 키워드의 순위 변동이에요: | 키워드 | 현재 순위 | 변동 | |--------|----------|------| | 강남 맛집 | 3위 | +2 | | 홍대 카페 | 7위 | -1 | | 성수동 브런치 | 12위 | 신규 | > 순위가 상승한 키워드가 있어요. 자세한 내용은 리포트를 확인해주세요. `ranking_score` 기반으로 계산됐어요.
지원 문법: 볼드, 이탤릭, 리스트, 테이블, 인라인 코드, 코드 블록, 블록인용, 링크 (새 탭), 수평선.
플러그인: remark-gfm (GitHub Flavored Markdown — 테이블, 취소선 등)
Spacing & Border Radius
Border Radius
Shadow
States
서비스 전반에서 사용하는 로딩, 에러, 빈 상태 패턴이에요.
Loading — Spinner
Loader2 + animate-spin 조합. 버튼 내부에 넣어 비동기 처리 상태를 표시해요.
Loading — Skeleton 조합
카드 목록, 테이블 행, 상품 그리드 등 데이터 로딩 시 콘텐츠 형태에 맞춰 Skeleton을 배치해요.
Error States
경고(amber), 에러(red), 정보(blue) 3가지 스타일. border-[color]-200 bg-[color]-50/30 패턴.
Empty State
아직 주문 내역이 없어요
서비스를 이용하면 여기에 주문 내역이 표시돼요.
아이콘 + 제목 + 설명 + CTA 버튼 구성. 데이터가 없을 때 사용해요.
Toast
sonner 기반 토스트 알림. useToast() 훅으로 사용해요.import { useToast } from '@/hooks/use-toast'
const toast = useToast(); toast.success("저장이 완료됐어요."); toast.error("결제 처리 중 오류가 발생했어요."); toast.warning("포인트가 부족해요."); toast.info("새로운 알림이 있어요."); // API 에러 자동 번역 toast.errorFromApi(err, "기본 메시지");
translateErrorMessage()로 영문 API 에러를 자동 한글 변환해요 (Unauthorized → "로그인이 필요해요." 등).
Animations
globals.css에 정의된 커스텀 애니메이션이에요.
btn-glow (시머 + 글로우)
/* 사용법 */ <Button className="btn-glow">결제하기</Button> /* 효과: shimmer(빛 줄기 흐름) + glow-pulse(은은한 발광) */
service-detail-help-icon
<span className="service-detail-help-icon">?</span> /* 클릭 시 펄스: service-detail-help-icon--pulse 클래스 추가 */
animate-spin
Tailwind animate-spin — Loader2 아이콘과 함께 사용.
Forms
폼 필드 패턴: 필수 표시, 에러 메시지, 도움말 텍스트, 글자수 카운터.
필수 필드 + 도움말
카카오 비즈니스 → 광고계정 관리에서 확인할 수 있어요.
에러 상태 + 글자수 카운터
광고주ID는 숫자만 입력 가능해요.
16/1,000
동의 체크박스 패턴
Layout
서비스 페이지의 레이아웃 구조예요. 실제 컴포넌트는 components/layout/에 있어요.
전체 화면 구조
모바일: Sidebar → Sheet(슬라이드)로 전환. components/layout/mobile-nav.tsx
주문 폼 레이아웃 (3단)
grid grid-cols-1 md:grid-cols-3 — 모바일에서는 1단, 데스크탑에서는 3단. 오른쪽은 sticky top-20.
레이아웃 컴포넌트 목록
header.tsx로고, 네비, 알림벨, 유저메뉴, 포인트 잔액sidebar.tsxAPI 기반 동적 사이드바 메뉴mobile-nav.tsx모바일 햄버거 메뉴 (Sheet)notification-bell.tsx실시간 활동 알림announcement-bar.tsx상단 공지 배너server-status-banner.tsx서비스 점검 안내 배너SelectableCard
상품/옵션 선택에 사용하는 카드. 선택 시 파란 테두리 + 체크 아이콘이 표시돼요.import { SelectableCard } from '@/components/service-page/SelectableCard'
카카오 모먼트 광고비의 최대 8%를 환급받으세요.
카카오 키워드광고 광고비의 최대 8%를 환급받으세요.
카카오 브랜드검색 광고비의 최대 8%를 환급받으세요.
ProductCard
기존 상품 선택용 카드. SelectableCard보다 가볍고, ProductServicePage에서 사용돼요.import { ProductCard } from '@/components/service-page/ProductCard'
SelectableCard vs ProductCard: SelectableCard은 border-2 + 체크 아이콘으로 선택이 명확한 단독 선택 UI. ProductCard는 border-1로 가볍고, 리스트 내 빠른 선택에 적합해요.
SuccessModal
주문/신청 완료 시 표시하는 성공 모달. 녹색 체크 아이콘 + 제목 + 설명 + 액션 버튼.import { SuccessModal } from '@/components/service-page/SuccessModal'
ValuePropsGrid
서비스 핵심 혜택을 아이콘 + 텍스트 그리드로 보여주는 컴포넌트.import { ValuePropsGrid } from '@/components/service-page/ValuePropsGrid'
EligibilityCard
환급 가능/불가 항목을 체크/X 아이콘으로 보여주는 정보 카드.import { EligibilityCard } from '@/components/service-page/EligibilityCard'
환급 불가 영역만 집행 중이라면 신청해도 환급이 발생하지 않아요.
MobileBottomCTA
모바일에서만 표시되는 하단 고정 CTA 바. 데스크탑에서는 숨겨져요.import { MobileBottomCTA } from '@/components/service-page/MobileBottomCTA'
Props:
visible, label, onClick, loading, disabled, children (왼쪽 정보 영역)Pricing
포인트/가격 표시 규칙. @repo/shared의 formatPoint 사용.
포인트 표시
환급률/뱃지 표시
// 포맷 함수 (from @repo/shared) formatPoint(3500) → "3,500P" formatPoint(3500, true) → "3,500P" (suffix 포함) formatPrice(50000) → "50,000원" formatNumber(1234567) → "1,234,567"
Steps
서비스 진행 단계를 시각화하는 패턴이에요.
프로세스 스텝 (가로형)
진행 상태 스텝 (상태별 색상)
완료(CheckCircle2), 진행중(Loader2 spin), 대기(Circle)
Upload
파일 업로드 UI 패턴. hidden input + trigger button 조합이에요.
기본 업로드 버튼
업로드 완료 상태
// 패턴: hidden input + ref trigger <input ref={fileInputRef} type="file" accept="image/*" className="hidden" onChange={handleFileChange} /> <Button variant="outline" onClick={() => fileInputRef.current?.click()}> <Upload /> 파일 선택 </Button> // 업로드 API const formData = new FormData(); formData.append("files", file); formData.append("fileType", "npress-order"); await apiClient.upload("/v1/upload/files", formData);
Gradients
버튼, 히어로 배경, 오버레이에 사용하는 그라데이션 팔레트예요.
버튼 그라데이션
배경 그라데이션
오버레이 투명도
모달 딤: bg-black/50, 가벼운 딤: bg-black/20
InlineAlert
페이지 내 인라인 알림 카드. 현재 어드민에는 Alert 컴포넌트가 있고, web에서는 수동으로 조합해 사용해요.
// 색상 패턴 규칙 success: border-green-200 bg-green-50/30 + text-green-800 error: border-red-200 bg-red-50/30 + text-red-800 warning: border-amber-200 bg-amber-50/30 + text-amber-800 info: border-blue-200 bg-blue-50/30 + text-blue-800
Responsive
Tailwind 모바일 퍼스트 반응형 패턴. 기본 = 모바일, md: (768px~) = 데스크탑.
브레이크포인트
자주 쓰는 반응형 패턴
hidden md:flex모바일 숨김, 데스크탑 표시 (사이드바)md:hidden모바일만 표시 (햄버거 메뉴)grid-cols-1 md:grid-cols-3모바일 1단 → 데스크탑 3단grid-cols-2 sm:grid-cols-4모바일 2단 → 태블릿+ 4단p-3 md:p-6모바일 좁은 패딩 → 데스크탑 넓은 패딩text-[11px] md:text-xs모바일 11px → 데스크탑 12pxfixed bottom-16 ... md:hidden모바일 고정 CTA (MobileBottomCTA)TaskStatus
주문/태스크 처리 상태를 표시하는 뱃지 4종이에요.
// 상태 색상 규칙 PENDING: gray-100/600 + Clock PROCESSING: blue-50/600 + Loader2 spin COMPLETED: green-50/600 + CheckCircle2 FAILED: red-50/600 + XCircle
AdminRef
어드민(apps/admin/src/components/ui/)에만 있는 컴포넌트. 웹에서 필요하면 참고해서 추가할 수 있어요.
alert.tsx인라인 알림 (success/error/warning/info). 닫기 버튼, 아이콘, 제목 지원.
switch.tsx토글 스위치 (default/small). SwitchRow로 라벨+설명 조합 가능.
tooltip.tsx호버 툴팁. top/bottom/left/right 4방향. 최대 260px.
number-input.tsx콤마 포맷 숫자 입력. min/max 검증. 1000 → 1,000 자동 변환.
Timing
프로젝트에서 사용하는 애니메이션 타이밍 가이드라인이에요.
| 용도 | Duration | Easing | 예시 |
|---|---|---|---|
| 호버/포커스 | 0.2s | ease | 버튼 hover scale, 카드 shadow |
| 모달/시트 진입 | 0.3s | ease-out | Dialog, Sheet 열기 |
| 아이콘 펄스 | 0.4s | ease | service-detail-help-icon 클릭 |
| 스크롤 이동 | smooth | — | scrollIntoView({ behavior: 'smooth' }) |
| 시머 효과 | 2.5s | ease-in-out | btn-glow shimmer |
| 글로우 펄스 | 2s | ease-in-out | btn-glow box-shadow 호흡 |
| 스피너 | 1s | linear | animate-spin (Loader2) |
원칙: 인터랙션 피드백은 0.2s, 패널 전환은 0.3s, 장식 애니메이션은 2~2.5s infinite.