zioinfo-mail/.claude/skills/design-token-system/SKILL.md
DESKTOP-TKLFCPR\ython df375c83c0 feat(design-harness): UI overhaul harness + /design bot command
Agents:
- ui-scout: Playwright MCP + Variant(variant.com/community) visual capture
- design-system-architect: unified design tokens (CSS vars / RN StyleSheet)
- component-refactor-engineer: per-system component refactoring
- visual-qa-tester: before/after screenshot comparison

Skills:
- ui-overhaul-orchestrator: E2E pipeline (capture->tokens->refactor->QA)
- playwright-visual-capture: Playwright MCP + Variant workflow
- design-token-system: tokens.css with Pretendard, 4px grid, brand colors
- component-refactor: Button/Card/Badge patterns for 4 systems

Bot: /design capture|variant|tokens|homepage|itsm|manager|app|qa|ab

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-31 18:15:13 +09:00

5.9 KiB

name description
design-token-system zio 4개 시스템(홈페이지·ITSM·Manager·Messenger) 통합 디자인 토큰 설계·구현 스킬. Pretendard 폰트, 딥블루+스카이블루 브랜드 색상, 4px 간격 시스템을 CSS변수·Tailwind·React Native StyleSheet로 변환한다. 다음 상황에서 반드시 사용: (1) '디자인 토큰 만들어줘', '색상 시스템 정의', '폰트 통일'; (2) tokens.css 생성/수정; (3) CSS 변수 리팩토링; (4) 다시 실행, 업데이트, 보완.

zio 통합 디자인 토큰 시스템

적용 파일 위치

시스템 파일
홈페이지 workspace/zioinfo-web/frontend/src/styles/tokens.css
ITSM itsm/static/tokens.css
Manager manager/frontend/src/styles/tokens.css
Messenger app/constants/tokens.ts

tokens.css (홈페이지·Manager 공용)

/* ── zio 통합 디자인 토큰 ── */

/* 폰트 */
@import url('https://cdn.jsdelivr.net/gh/orioncactus/pretendard/dist/web/static/pretendard.css');

:root {
  /* ── 브랜드 색상 ── */
  --color-primary-50:  #eff4ff;
  --color-primary-100: #dbe4ff;
  --color-primary-200: #bac8ff;
  --color-primary-300: #91b4fa;
  --color-primary-400: #4d7ef5;
  --color-primary-500: #0051A2;
  --color-primary-600: #003f7f;
  --color-primary-700: #002d5c;
  --color-primary-800: #001c3a;
  --color-primary-900: #000d1a;

  --color-accent-400: #38bdf8;
  --color-accent-500: #00A3E0;
  --color-accent-600: #0082b3;

  /* ── 뉴트럴 ── */
  --color-neutral-0:   #ffffff;
  --color-neutral-50:  #f8fafc;
  --color-neutral-100: #f1f5f9;
  --color-neutral-200: #e2e8f0;
  --color-neutral-300: #cbd5e1;
  --color-neutral-400: #94a3b8;
  --color-neutral-500: #64748b;
  --color-neutral-600: #475569;
  --color-neutral-700: #334155;
  --color-neutral-800: #1e293b;
  --color-neutral-900: #0f172a;

  /* ── 시맨틱 ── */
  --color-success:     #22c55e;
  --color-success-bg:  #f0fdf4;
  --color-warning:     #f59e0b;
  --color-warning-bg:  #fffbeb;
  --color-danger:      #ef4444;
  --color-danger-bg:   #fef2f2;
  --color-info:        #3b82f6;
  --color-info-bg:     #eff6ff;

  /* ── 타이포 ── */
  --font-family: 'Pretendard', 'Apple SD Gothic Neo', 'Noto Sans KR', sans-serif;
  --font-mono:   'JetBrains Mono', 'Fira Code', monospace;

  --text-xs:   11px;
  --text-sm:   13px;
  --text-base: 15px;
  --text-lg:   17px;
  --text-xl:   20px;
  --text-2xl:  24px;
  --text-3xl:  30px;
  --text-4xl:  36px;
  --text-5xl:  48px;

  --font-normal:   400;
  --font-medium:   500;
  --font-semibold: 600;
  --font-bold:     700;
  --font-black:    900;

  --leading-tight:  1.25;
  --leading-normal: 1.6;
  --leading-loose:  1.8;

  /* ── 간격 (4px 기반) ── */
  --space-0:  0px;
  --space-1:  4px;
  --space-2:  8px;
  --space-3:  12px;
  --space-4:  16px;
  --space-5:  20px;
  --space-6:  24px;
  --space-8:  32px;
  --space-10: 40px;
  --space-12: 48px;
  --space-16: 64px;
  --space-20: 80px;
  --space-24: 96px;

  /* ── 반경 ── */
  --radius-xs:   2px;
  --radius-sm:   4px;
  --radius-md:   8px;
  --radius-lg:   12px;
  --radius-xl:   16px;
  --radius-2xl:  24px;
  --radius-full: 9999px;

  /* ── 그림자 ── */
  --shadow-xs: 0 1px 2px rgba(0,0,0,.06);
  --shadow-sm: 0 1px 3px rgba(0,0,0,.08), 0 1px 2px rgba(0,0,0,.06);
  --shadow-md: 0 4px 6px rgba(0,0,0,.07), 0 2px 4px rgba(0,0,0,.06);
  --shadow-lg: 0 10px 15px rgba(0,0,0,.10), 0 4px 6px rgba(0,0,0,.05);
  --shadow-xl: 0 20px 25px rgba(0,0,0,.10), 0 10px 10px rgba(0,0,0,.04);

  /* ── 전환 ── */
  --ease-fast:   150ms cubic-bezier(.4,0,.2,1);
  --ease-normal: 250ms cubic-bezier(.4,0,.2,1);
  --ease-slow:   400ms cubic-bezier(.4,0,.2,1);

  /* ── 레이아웃 ── */
  --container-sm:  640px;
  --container-md:  768px;
  --container-lg:  1024px;
  --container-xl:  1280px;
  --container-2xl: 1536px;

  /* ── Z-index ── */
  --z-dropdown: 100;
  --z-modal:    200;
  --z-toast:    300;
  --z-tooltip:  400;
}

/* ── 다크모드 (ITSM 전용) ── */
[data-theme="dark"] {
  --color-neutral-0:   #0f172a;
  --color-neutral-50:  #1e293b;
  --color-neutral-100: #334155;
  --color-neutral-200: #475569;
  --bg-page:    #0f172a;
  --bg-surface: #1e293b;
  --bg-card:    #1e293b;
  --text-main:  #f1f5f9;
  --text-muted: #94a3b8;
  --border:     #334155;
}

/* ── 라이트모드 ── */
:root, [data-theme="light"] {
  --bg-page:    var(--color-neutral-50);
  --bg-surface: var(--color-neutral-0);
  --bg-card:    var(--color-neutral-0);
  --text-main:  var(--color-neutral-900);
  --text-muted: var(--color-neutral-500);
  --border:     var(--color-neutral-200);
}

/* ── 글로벌 리셋 ── */
*, *::before, *::after { box-sizing: border-box; }
body {
  font-family: var(--font-family);
  font-size: var(--text-base);
  line-height: var(--leading-normal);
  color: var(--text-main);
  background: var(--bg-page);
  -webkit-font-smoothing: antialiased;
}

tokens.ts (Messenger RN)

// app/constants/tokens.ts
export const colors = {
  primary:  { 50:'#eff4ff', 500:'#0051A2', 600:'#003f7f' },
  accent:   { 400:'#38bdf8', 500:'#00A3E0' },
  neutral:  { 0:'#fff', 50:'#f8fafc', 100:'#f1f5f9', 200:'#e2e8f0',
              500:'#64748b', 700:'#334155', 900:'#0f172a' },
  success:  '#22c55e',
  warning:  '#f59e0b',
  danger:   '#ef4444',
  info:     '#3b82f6',
} as const;

export const spacing = {
  1:4, 2:8, 3:12, 4:16, 5:20, 6:24, 8:32, 10:40, 12:48,
} as const;

export const radii = {
  sm:4, md:8, lg:12, xl:16, full:9999,
} as const;

export const shadows = {
  sm: { shadowColor:'#000', shadowOffset:{width:0,height:1}, shadowOpacity:.06, shadowRadius:3, elevation:2 },
  md: { shadowColor:'#000', shadowOffset:{width:0,height:4}, shadowOpacity:.08, shadowRadius:6, elevation:4 },
} as const;

export const typography = {
  xs:11, sm:13, base:15, lg:17, xl:20, '2xl':24, '3xl':30,
} as const;