Design System · v1.0

BizCopilot Design System

assets/const.less 토큰과 공용 컴포넌트를 한 화면에서 확인하고, 새 화면을 같은 원칙으로 빠르게 설계하기 위한 살아있는 가이드입니다.
27 color tokens
18 component patterns

01

Color Palette

assets/const.less 에 정의된 브랜드, 텍스트, 표면, 상태 컬러입니다. 토큰 카드를 누르면 이름과 값을 복사합니다.

Brand Colors

핵심 CTA, 활성 상태, 브랜드 인지에 사용합니다.

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 123
Typography Principles
  • 페이지 제목, 섹션 제목, 본문, 보조 정보의 네 단계가 먼저 읽혀야 합니다.
  • 긴 한글 설명은 1.625 행간과 keep-all 줄바꿈으로 읽기 흐름을 지킵니다.
  • 숫자와 상태가 많은 업무 화면에서는 장식보다 빠른 판독을 우선합니다.

Usage Guide

역할에 맞는 기존 단계를 선택하고 화면별 임의 크기 추가를 피합니다.
기업의 다음 성장을 설계합니다
Hero / Page Title 랜딩 히어로와 핵심 페이지의 첫 제목
@font-size-6xl / 800 / 1.2
특허 출원 준비
Section Title 큰 섹션과 주요 단계 제목
@font-size-4xl / 800 / 1.2
AI 초안 검토
Card / Panel Title 카드, 모달, 사이드 패널 제목
@font-size-xl / 700 / 1.375
입력한 내용을 바탕으로 출원 초안을 준비합니다.
Body 본문, 폼 값, 설명 문장
@font-size-base / 400 / 1.625
다음 단계
Label / Button 입력 라벨, 버튼, 탭, 상태 배지
@font-size-sm / 700 / 1.5
마지막 저장 2026.07.28 14:30
Caption / Meta 도움말, 메타 정보, 표 헤더
@font-size-xs / 500 / 1.5

03

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
Success success

저장이 완료되었습니다.

Info info

새로운 업데이트가 있습니다.

Warning warning
Error error
<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.vue
텍스트 text
문서 목록을 불러오는 중
아이콘 목록 list-icon
알림 목록을 불러오는 중
일반 목록 list
업무 목록을 불러오는 중
카드 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.vue
DOCUMENT 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만으로 입력 목적을 설명하거나 오류를 색상만으로 표현하지 않습니다.
  • 로딩 중인 버튼을 계속 누를 수 있게 두거나 진행 상태를 숨기지 않습니다.
  • 데스크톱에서만 읽히는 고정 폭과 작은 글자 크기를 사용하지 않습니다.