Design System · v1.0
BizCopilot Design System
assets/const.less
토큰과 공용 컴포넌트를 한 화면에서 확인하고, 새 화면을 같은 원칙으로 빠르게 설계하기 위한 살아있는 가이드입니다.
01
Color Palette
assets/const.less
에 정의된 브랜드, 텍스트, 표면, 상태 컬러입니다. 토큰 카드를 누르면 이름과 값을 복사합니다.
Text & Surface
텍스트 위계, 페이지 표면, 카드와 경계선에 사용합니다.Semantic Colors
성공, 주의, 오류, 정보 상태를 배경과 전경의 한 쌍으로 사용합니다.Extended Palette
차트와 서비스 구분처럼 다중 범주가 필요할 때만 제한적으로 사용합니다.02
Typography
정보 위계와 읽기 속도를 우선하는 BizCopilot의 한글 타이포그래피 기준입니다.Primary Typeface
Pretendard / Noto Sans KR
"Pretendard", -apple-system, BlinkMacSystemFont, system-ui, Roboto, "Helvetica Neue", "Segoe UI", "Apple SD Gothic Neo", "Noto Sans KR", "Malgun Gothic", sans-serif 기업의 다음 성장을 설계합니다. ABC 123Typography Principles
- 페이지 제목, 섹션 제목, 본문, 보조 정보의 네 단계가 먼저 읽혀야 합니다.
- 긴 한글 설명은 1.625 행간과 keep-all 줄바꿈으로 읽기 흐름을 지킵니다.
- 숫자와 상태가 많은 업무 화면에서는 장식보다 빠른 판독을 우선합니다.
Usage Guide
역할에 맞는 기존 단계를 선택하고 화면별 임의 크기 추가를 피합니다.
기업의 다음 성장을 설계합니다
@font-size-6xl / 800 / 1.2
특허 출원 준비
@font-size-4xl / 800 / 1.2
AI 초안 검토
@font-size-xl / 700 / 1.375
입력한 내용을 바탕으로 출원 초안을 준비합니다.
@font-size-base / 400 / 1.625
다음 단계
@font-size-sm / 700 / 1.5
마지막 저장 2026.07.28 14:30
@font-size-xs / 500 / 1.503
Foundation Tokens
간격, 모서리, 그림자, 컨트롤 높이는 화면별 임의 값 대신 아래 제한된 단계를 사용합니다.Spacing
4px 기반의 간격 단계입니다. 컴포넌트 내부와 섹션 간격을 같은 리듬으로 맞춥니다.@spacing-xs 4px 아이콘과 라벨 @spacing-sm 8px 작은 gap @spacing-md 12px 폼 내부 @spacing-lg 16px 기본 gap @spacing-xl 20px 작은 카드 @spacing-2xl 24px 카드 내부 @spacing-3xl 32px 섹션 내부 @spacing-5xl 48px 큰 블록 @spacing-6xl 64px 섹션 사이 Radius
작은 컨트롤에서 큰 패널까지 크기에 맞춰 반경을 키웁니다.@border-radius-sm 6px 작은 배지 @border-radius-md 8px 버튼 @border-radius-lg 12px 입력 / 작은 카드 @border-radius-xl 16px 기본 카드 @border-radius-2xl 24px 대형 패널 @border-radius-3xl 32px 히어로 @border-radius-full 9999px pill / dot Shadow
표면의 위계를 나타냅니다. 기본 카드에는 작은 그림자만 사용합니다.@shadow-sm 0 2px 8px rgba(0, 0, 0, 0.04) 기본 카드 @shadow-base 0 4px 16px rgba(0, 0, 0, 0.08) hover 카드 @shadow-md 0 8px 24px rgba(0, 0, 0, 0.12) 드롭다운 @shadow-lg 0 16px 48px rgba(0, 0, 0, 0.16) 오버레이 @shadow-primary 0 8px 24px rgba(49, 130, 246, 0.25) Primary CTA Controls & Layout
버튼과 입력 높이, 컨테이너, 반응형 경계값입니다.@control-height-sm 36px 작은 버튼 @control-height-md 44px 기본 버튼 @control-height-lg 52px 입력 / 큰 버튼 @container-max-width 1200px 기본 콘텐츠 @container-padding 24px 데스크톱 좌우 @screen-md 768px 모바일 전환 @screen-lg 1024px 태블릿 전환 04
Core Components
문서 예시가 아니라 실제 화면에서 import해 사용할 수 있는 Vue 2 공용 컴포넌트입니다.Actions
Button
components/ds/DsButton.vue<DsButton variant="primary">다음 단계</DsButton>
<DsButton variant="secondary">임시 저장</DsButton>
<DsButton variant="ghost">이전</DsButton>
<DsButton variant="danger">삭제</DsButton>
<DsButton :loading="saving" loading-label="저장 중">저장</DsButton>Form
Field
components/ds/DsField.vue진행 알림을 받을 이메일을 입력해주세요.
회사명을 입력해주세요.
숫자만 입력하면 국내 전화번호 형식으로 구분됩니다.
실제 v-model 01029730833
뒷자리 첫 숫자를 제외한 값은 화면에서 자동으로 가려집니다.
주민등록번호 실제 v-model 8901091076323
숫자만 저장하고 화면에서는 3-2-5 단위로 구분합니다.
숫자만 저장하고 화면에서는 6-7 단위로 구분합니다.
시스템에서 자동으로 업데이트하는 값입니다.
<DsField
id="company-name"
v-model="form.companyName"
label="회사명"
placeholder="회사명을 입력해주세요."
help="사업자등록증과 같은 이름을 사용해주세요."
:error="errors.companyName"
required />
<DsField
id="phone"
v-model="form.phone"
format="phone"
label="전화번호"
placeholder="010 0000 0000"
inputmode="numeric"
autocomplete="tel"
required />
<DsField
id="resident-number"
v-model="form.residentNumber"
format="resident-number"
label="주민등록번호"
inputmode="numeric"
autocomplete="off"
required />
<DsField id="idea" v-model="form.idea" label="아이디어 설명" multiline :rows="5" />Form
Postcode Field
components/ds/DsPostcodeField.vue검색 결과로 선택한 우편번호가 자동으로 입력됩니다.
<DsPostcodeField
id="postcode"
v-model="form.zipcode"
label="우편번호"
help="검색 결과로 선택한 우편번호가 자동으로 입력됩니다."
required
@search="searchAddress" />Form
File Upload
components/ds/DsFileUpload.vue파일을 드래그해 놓거나
PDF, DOC, DOCX, JPG, PNG · 파일당 최대 10MB
<DsFileUpload
id="evidence-files"
v-model="form.files"
label="증빙 자료"
accept=".pdf,.doc,.docx,.jpg,.jpeg,.png"
:max-size-mb="10"
multiple
required
@invalid="handleInvalidFile" />Feedback
Badge
components/ds/DsBadge.vue 검토 전 작성 중 제출 완료 확인 필요 처리 실패
<DsBadge tone="neutral" label="검토 전" dot />
<DsBadge tone="info" label="작성 중" dot />
<DsBadge tone="success" label="제출 완료" dot />
<DsBadge tone="warning" label="확인 필요" dot />
<DsBadge tone="danger" label="처리 실패" dot />Overlays
Dialog & Toast
DsDialog · DsToast · vue-toastification<DsButton @click="dialogOpen = true">Dialog 열기</DsButton>
<DsDialog
id="save-data-dialog"
v-model="dialogOpen"
title="데이터 입력 확정"
description="현재 데이터를 워크스페이스에 저장합니다."
confirm-label="확정"
cancel-label="취소"
@confirm="saveData" />
<DsToast
v-model="toastOpen"
tone="success"
message="저장이 완료되었습니다."
action-label="확인"
@action="toastOpen = false" />
// 전역 자동 닫기와 스택이 필요할 때
this.$toast.success("저장이 완료되었습니다.")05
Product States
정상 화면만 만들지 않습니다. 로딩, 빈 상태, 오류, 비활성 경계를 같은 컴포넌트 언어로 안내합니다.Boundary
Loading, Disabled, Error
loading · disabled · error 분석 중 다시 시도 필요
휴대폰 번호를 모두 입력해주세요.
<DsButton :loading="generating" loading-label="AI 초안 생성 중">초안 생성</DsButton>
<DsButton :disabled="!canContinue" variant="ghost">선택 필요</DsButton>
<DsField
id="phone"
v-model="phone"
format="phone"
label="연락처"
:error="phoneError"
required />Loading Placeholder
Skeleton Patterns
components/ds/DsSkeleton.vuetext문서 목록을 불러오는 중
list-iconlist업무 목록을 불러오는 중
card출원 카드를 불러오는 중
pattern대시보드를 불러오는 중
<DsSkeleton :lines="4" label="문서 목록을 불러오는 중" />
<DsSkeleton variant="list-icon" :items="4" label="알림 목록을 불러오는 중" />
<DsSkeleton variant="list" :items="4" label="업무 목록을 불러오는 중" />
<DsSkeleton variant="card" :lines="3" label="출원 카드를 불러오는 중" />
<DsSkeleton
variant="custom"
:pattern="['title', 'subtitle', 'spacer:20', 'card', 'list-icon', 'list-icon']"
label="대시보드를 불러오는 중" />Long-running AI Task
AI Process Loading
components/ds/DsProcessLoading.vueDOCUMENT GENERATION
문서 작성 중
입력한 내용을 분석해 출원에 필요한 문서를 구조화하고 있습니다.
AI 처리 중 · 잠시만 기다려주세요DRAWING GENERATION
도면 생성 중
확정된 명세서를 바탕으로 이해하기 쉬운 특허 도면을 생성하고 있습니다.
AI 처리 중 · 잠시만 기다려주세요<DsProcessLoading kind="document" />
<DsProcessLoading kind="drawing" />
<DsProcessLoading
kind="document"
title="명세서 작성 중"
description="업로드한 자료를 분석해 명세서를 작성하고 있습니다." />No Data
Empty State
components/ds/DsEmptyState.vue아직 등록된 출원이 없습니다
새 출원을 시작하면 AI 초안부터 전문가 검토까지 진행 상태를 이곳에서 확인할 수 있습니다.
<DsEmptyState
title="아직 등록된 출원이 없습니다"
description="새 출원을 시작하면 진행 상태를 확인할 수 있습니다."
primary-label="새 출원 시작"
secondary-label="이용 가이드"
@primary="startApplication"
@secondary="openGuide" />06
Component Inventory
신규 화면은components/ds의 표준 컴포넌트를 우선 사용합니다. 기존 컴포넌트는 즉시 삭제하지 않고
기능 변경 시 점진적으로 전환합니다.
Component Usage Source Status
DsButton 주요/보조/텍스트/위험 액션과 로딩·비활성 상태
components/ds/DsButton.vue 표준DsField 라벨, 도움말, 오류, 전화번호·주민등록번호 포맷을 포함하는 input과 textarea
components/ds/DsField.vue 표준DsPostcodeField 읽기 전용 우편번호 값과 주소 검색 액션을 결합한 폼 입력
components/ds/DsPostcodeField.vue 표준DsFileUpload 클릭·드래그 앤 드롭 파일 선택, 형식·크기 검증, 선택 파일 제거
components/ds/DsFileUpload.vue 표준DsBadge 중립, 정보, 성공, 경고, 오류 상태
components/ds/DsBadge.vue 표준DsDialog 중요한 확인과 취소가 필요한 접근 가능한 대화상자
components/ds/DsDialog.vue 표준DsToast 성공, 정보, 경고, 오류 작업 결과와 선택적인 후속 액션
components/ds/DsToast.vue 표준DsEmptyState 데이터 없음과 다음 행동 안내
components/ds/DsEmptyState.vue 표준DsSkeleton 텍스트, 목록, 아이콘 목록, 카드와 커스텀 조합형 로딩 상태
components/ds/DsSkeleton.vue 표준DsProcessLoading 문서 작성과 도면 생성처럼 시간이 필요한 AI 작업
components/ds/DsProcessLoading.vue 표준AppHeader 서비스 전역 데스크톱/모바일 내비게이션
components/AppHeader.vue 유지BrandLogo 헤더, 폼, 대시보드 브랜드 서명
components/BrandLogo.vue 유지FileUploadCard 문서 업로드와 파일 상태 표시
components/FileUploadCard.vue 유지LoginDialog 인증이 필요한 흐름의 공용 로그인 모달
components/LoginDialog.vue 유지DropZone 드래그 앤 드롭 파일 입력
components/DropZone.vue 유지hhInput Vuetify 기반 레거시 단일 입력
components/hhInput.vue 전환 대상hhSelect Vuetify 기반 레거시 선택 입력
components/hhSelect.vue 전환 대상.toss-btn / .primary-btn 페이지 내부에 반복 선언된 레거시 버튼 스타일
pages/**/*.vue, components/**/*.vue 전환 대상07
Usage Principles
일관성은 새 규칙의 수가 아니라 같은 선택을 반복하는 데서 만들어집니다.Do
- 새 화면은 공용 컴포넌트부터 확인하고 가장 가까운 variant를 재사용합니다.
- 색, 간격, 반경, 그림자는 `assets/const.less` 토큰으로만 지정합니다.
- 버튼은 한 영역에 primary action 하나를 두고 나머지는 위계를 낮춥니다.
- 입력 오류는 필드 바로 아래에서 문제와 해결 방법을 함께 설명합니다.
- 빈 화면에는 현재 상태와 사용자가 이어서 할 수 있는 행동을 제공합니다.
Don’t
- 페이지마다 `.toss-btn`, `.primary-btn` 스타일을 다시 선언하지 않습니다.
- 브랜드 블루와 비슷한 임의 hex 컬러를 화면별로 추가하지 않습니다.
- placeholder만으로 입력 목적을 설명하거나 오류를 색상만으로 표현하지 않습니다.
- 로딩 중인 버튼을 계속 누를 수 있게 두거나 진행 상태를 숨기지 않습니다.
- 데스크톱에서만 읽히는 고정 폭과 작은 글자 크기를 사용하지 않습니다.