본문으로 건너뛰기
Centralby 디자인 시스템

시작하기

시작하기

센트럴바이 디자인 시스템의 약속, 원칙, 쓰는 법(가져오기·토큰·테마·언어)과 출시용·라이브러리 구분을 한 페이지에.

계약

디자인 시스템은 제품이 아니라 계약이다. 문서·코드·디자인은 한 원천에서 나온다.

센트럴바이는 흩어진 업무 기록에서 내가 해온 일을 찾아, 근거와 함께 기억하고 필요할 때 설명할 수 있게 돕는 개인 업무 기억 서비스다. 약속은 “You work. centralby remembers.” 이 시스템의 모든 규칙은 이 약속을 화면에서 지키기 위해 있다.

  • 컴포넌트의 문서는 meta 파일 하나다. 문서화하지 않은 prop은 tsc가 실패시킨다.
  • 색·크기·시간 값은 토큰에만 있다. 리터럴은 design:lint가 막는다.
  • 이 가이드의 값과 숫자는 실행 중인 CSS와 registry에서 읽는다. 문서가 코드보다 앞서거나 뒤처질 수 없다.

지금의 규모

컴포넌트
142
출시 화면에서 사용
71
라이브러리 전용
71
만들지 않는 이유 페이지
6
위젯
61 · 출시 12종
가이드 페이지
21

숫자는 이 페이지가 열릴 때 registry.ts·rulePages·오너 선택 위젯 목록(picks.ts)에서 직접 센다. 문서에 적은 숫자가 아니다.

원칙

제품 철학은 화면에서 쓰는 방식에 적용한다. 라이브러리에 차트가 있어도 생산성 점수에 쓰지 않는다는 식이다(DIRECTION §4).

  1. 기록과 근거를 먼저 보존한다. 추천·발견·보고서·경력 문장은 쌓인 기록을 활용하는 기능이다. 화려한 대시보드로 기록의 부족을 가리지 않는다.
  2. 사실과 해석을 구분한다. 원문에서 확인한 것, 시스템의 추정, 사용자의 진술을 나눈다. 메일 수신은 기여가 아니고 일정 초대는 참석이 아니다. 자료 수를 생산성 점수로 바꾸지 않는다.
  3. 자동화가 새 업무를 만들지 않는다. 결과는 들어오는 대로 보여주고, 검토는 기여 귀속·사실 충돌·외부에 쓸 문장처럼 중요한 지점에만 모은다.
  4. 사용자의 수정과 선택을 존중한다. 직접 쓴 설명은 자동 정리 때문에 사라지지 않는다. 합치기·나누기·연결 해제·되돌리기가 가능하다.
  5. 수집한 범위만 설명한다. 아직 읽지 않음, 읽었지만 결과 없음, 일부 실패를 구분한다. 접근할 수 없는 과거 자료를 복원한다고 약속하지 않는다.
  6. 필요한 순간의 효용으로 평가한다. 방문 횟수를 늘리려고 불필요한 확인이나 반복 행동을 만들지 않는다.

쓰는 법

가져오기

화면은 @/design 하나에서만 가져온다. meta·registry·catalog·*.preview.tsx는 공개 API가 아니다. 기존(legacy) 화면은 @/design을 가져올 수 없고, v4 코드는 @/ui를 가져올 수 없다(lint R6·R7).

import { Button, StateView, TrustLabel } from '@/design';

<StateView state="partial" surface="list">
  {rows}
</StateView>

컴포넌트는 className·style을 받지 않는다. 배치는 부모가, 모양은 토큰이 정한다. 나머지 네이티브 속성은 그대로 전달된다.

토큰

세 층이다: primitive(--p-*, 원시값, tokens 폴더 안에서만) → semantic(--cb-*, 역할 이름) → 컴포넌트 로컬 변수. 컴포넌트와 화면은 --cb-*만 쓴다.

.row {
  padding: var(--cb-space-3) var(--cb-space-4);
  border-bottom: var(--cb-border-width) solid var(--cb-line);
  color: var(--cb-ink);
  transition: background-color var(--cb-dur-fast) var(--cb-ease);
}

테마

라이트가 기본이고 다크를 함께 설계했다. <html data-theme="light|dark">가 있으면 그것을, 없으면 prefers-color-scheme을 따른다. themeScript가 첫 페인트 전에 적용해 깜빡임이 없다. 미리보기 프레임은 data-theme을 따로 줄 수 있다. 제품에는 테마 선택기가 없다(DIRECTION 1.6) — 선택기는 카탈로그 전용이다.

// (v4)/layout.tsx
<script dangerouslySetInnerHTML={{ __html: themeScript }} />

// a frame that is always dark
<div data-theme="dark">…</div>

언어

UI는 한국어·영어·중국어(간체)·스페인어 4개 언어다. <html lang>은 서버가 centralby_locale 쿠키로 정한다. 컴포넌트 안의 문구는 DesignLocaleProvider로 받는다. 사용자가 쓴 기록·작업 제목은 번역하지 않고, 언어를 모르면 dir="auto"만 붙인다.

<DesignLocaleProvider locale={locale}>
  <AppShell />
</DesignLocaleProvider>

스페인어가 가장 길다. 라벨은 한국어 대비 +35%를 수용해야 하고, 카탈로그의 “가장 긴 언어(es)” 토글로 확인한다.

출시용과 라이브러리

오너는 “하나의 방대한 디자인 시스템을 먼저 만들고, 앱 개발 때 필요한 것을 꺼내 쓴다”로 정했다. 그래서 모든 컴포넌트 meta에 launch가 있다. launch: true는 출시 화면(랜딩·/signup·/start·오늘·기록·나)이 실제로 쓰는 것이다. launch: false는 라이브러리에만 있고, 첫 소비자가 생길 때 true로 바꾼다.

  • 이렇게출시 화면은 launch: true 컴포넌트로 조립한다. 라이브러리 컴포넌트가 필요하면 먼저 meta를 true로 바꾸고 검토를 받는다.
  • 이렇게 하지 않기launch: false라고 품질 기준이 낮지 않다. 접근성·4개 언어·토큰 규칙은 같다.
분류별 출시용·라이브러리 수
분류전체출시라이브러리출시용 예
글자1073
레이아웃761
버튼과 동작422
입력1367
탐색1165
목록과 표시1569
상태와 알림16124
미디어와 구매505
차트909
날짜와 시간12210
편집 도구707
근거와 신뢰20191
기록과 경험927
위젯431

만들지 않는 것

라이브러리 범위에서는 v3-jh 목록을 모두 갖추지만, 제품 화면에서는 다음을 쓰지 않는다.

  • 테마 선택기, 외관 농도 조절, 폰트 선택기
  • 스프링 물리, 스크러빙, 시간축 스크러버
  • 활동 히트맵, streak, 생산성 수치, 점수, 순위
  • 10–11px 글자(최소 13px)

컴포넌트가 없는 대신 “만들지 않는 이유” 페이지를 둔 경우도 있다(예: RadarChart, ComboChart). 사이드바에서 해당 분류 끝에 있다.

다음에 볼 곳

컴포넌트 목록은 사이드바의 “모든 컴포넌트”, 원시값과 의미 토큰 전체는 “디자인 토큰”, 위젯은 “위젯”에 있다.

@/design · src/design/tokens/*.css · src/design/registry.ts

근거 문서: PRODUCT_BRIEF.md · DIRECTION.md §1.6 §2 §4 · TEAM.md §8 · round-3/daniel-build.md · src/design/registry.ts