MarketPilot Design System

UI 컴포넌트 & 스타일 가이드

v1.1

Colors

Primary#00B0F0
Primary Hover#009dd6
Primary Light#e6f7fd
Destructive#ef4444
Success#22c55e
Warning#f59e0b
Background#ffffff
Foreground#0a0a0a
Muted#f5f5f5
Muted FG#737373
Border#e5e5e5
Accent#f5f5f5

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)

Button

Variants

Gradient & Highlight

Sizes

States

Badge

Default
Secondary
Outline
Destructive
Success
Warning

Input & Textarea

Input

Textarea

Select

Radix Select

Card

기본 카드

카드 설명 텍스트

카드 본문 콘텐츠가 여기에 들어가요.

액션 카드

Footer가 있는 카드

버튼이 있는 카드 예시예요.

통계 카드

1,234

총 주문 수

Avatar

User
CN
MP
AB
XL

Table

주문번호상품상태금액
ORD-001N플레이스 트래픽
완료
50,000원
ORD-002블로그 리뷰
진행중
120,000원
ORD-003인스타 팔로워
취소
30,000원

Tabs

첫 번째 탭 콘텐츠예요. 개요 정보가 표시돼요.

Dialog

Sheet

Dropdown Menu

Popover

Calendar

2026년 3월

Skeleton

Separator

Horizontal

위 영역

아래 영역

Vertical

왼쪽
가운데
오른쪽

Spacing & Border Radius

Border Radius

sm6px
md8px
lg12px
xl16px
full9999px

Shadow

sm
default
md
lg

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

?hover 시 scale(1.15) 확대. 클릭 시 pulse 애니메이션.

<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/에 있어요.

전체 화면 구조

Header로고 · 네비 · 알림벨 · 유저메뉴
Sidebar
메뉴 1
메뉴 2
메뉴 3
Page Content
각 페이지의 고유 콘텐츠 영역

모바일: Sidebar → Sheet(슬라이드)로 전환. components/layout/mobile-nav.tsx

주문 폼 레이아웃 (3단)

왼쪽: 폼 영역 (col-span-2)
계정 정보 카드
요청사항 카드
오른쪽: Sticky 사이드바
신청 요약 + CTA

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'

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'

캠페인은 내가 직접 관리
💰광고비의 최대 8% 환급
🎁환급금은 마켓파일럿 포인트로 지급
🔄신청 1회 → 매월 자동 적용

EligibilityCard

환급 가능/불가 항목을 체크/X 아이콘으로 보여주는 정보 카드.
import { EligibilityCard } from '@/components/service-page/EligibilityCard'

환급 가능 광고 영역
파워링크
쇼핑검색광고
브랜드검색광고
GFA (디스플레이)
플레이스 검색광고
파워콘텐츠 (블로그)

환급 불가 영역만 집행 중이라면 신청해도 환급이 발생하지 않아요.

MobileBottomCTA

모바일에서만 표시되는 하단 고정 CTA 바. 데스크탑에서는 숨겨져요.
import { MobileBottomCTA } from '@/components/service-page/MobileBottomCTA'

모바일 기기(768px 미만)에서만 보여요. 화면 하단에 고정된 카드 형태의 CTA 버튼이에요.
Props: visible, label, onClick, loading, disabled, children (왼쪽 정보 영역)

Pricing

포인트/가격 표시 규칙. @repo/sharedformatPoint 사용.

포인트 표시

단가50P
할인가
100P80P
총 결제 금액3,500P

환급률/뱃지 표시

최대 8% 환급
신청 무료
50% 할인
무료

// 포맷 함수 (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 조합이에요.

기본 업로드 버튼

선택된 파일 없음

업로드 완료 상태

product-image-final.jpg

// 패턴: 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

버튼, 히어로 배경, 오버레이에 사용하는 그라데이션 팔레트예요.

버튼 그라데이션

Bluefrom-primary to-[#0066FF]
Warmfrom-[#FF6B6B] to-[#FF8E53]
Purplefrom-[#7C3AED] to-[#DB2777]

배경 그라데이션

Hero Purple
Subtle Primary

오버레이 투명도

20%
30%
50%
White 90%

모달 딤: bg-black/50, 가벼운 딤: bg-black/20

InlineAlert

페이지 내 인라인 알림 카드. 현재 어드민에는 Alert 컴포넌트가 있고, web에서는 수동으로 조합해 사용해요.

이관 신청이 완료됐어요.
결제 처리 중 오류가 발생했어요.
포인트가 부족해요. 충전 후 다시 시도해주세요.
이 서비스는 영업일 기준 1~2일 내 처리돼요.

// 색상 패턴 규칙 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~) = 데스크탑.

브레이크포인트

모바일< 768px
기본 스타일
데스크탑≥ 768px
md: 접두어

자주 쓰는 반응형 패턴

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 → 데스크탑 12px
fixed 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/)에만 있는 컴포넌트. 웹에서 필요하면 참고해서 추가할 수 있어요.

Alertalert.tsx

인라인 알림 (success/error/warning/info). 닫기 버튼, 아이콘, 제목 지원.

저장됐어요.
Switchswitch.tsx

토글 스위치 (default/small). SwitchRow로 라벨+설명 조합 가능.

OFFON
Tooltiptooltip.tsx

호버 툴팁. top/bottom/left/right 4방향. 최대 260px.

툴팁 내용이에요
ConfirmDialogconfirm-dialog.tsx

삭제 등 위험 액션 확인 모달. async 처리, 로딩 상태 지원.

NumberInputnumber-input.tsx

콤마 포맷 숫자 입력. min/max 검증. 1000 → 1,000 자동 변환.

Timing

프로젝트에서 사용하는 애니메이션 타이밍 가이드라인이에요.

용도DurationEasing예시
호버/포커스0.2sease버튼 hover scale, 카드 shadow
모달/시트 진입0.3sease-outDialog, Sheet 열기
아이콘 펄스0.4seaseservice-detail-help-icon 클릭
스크롤 이동smoothscrollIntoView({ behavior: 'smooth' })
시머 효과2.5sease-in-outbtn-glow shimmer
글로우 펄스2sease-in-outbtn-glow box-shadow 호흡
스피너1slinearanimate-spin (Loader2)

원칙: 인터랙션 피드백은 0.2s, 패널 전환은 0.3s, 장식 애니메이션은 2~2.5s infinite.