HomeFeedAbout

디자인 시스템 만들기 2일차 - Color CSS 세팅

김성현 1개월 전

어제 수집한 토큰을 바탕으로 색상 CSS 변수를 세팅해줬습니다.
세팅하기 전에 먼저 https://po4tion.dev/biome 를 참고해 프로젝트에 Biome를 세팅해줍니다.

Palette 세팅

Atomic 색상 토큰들은 아래처럼 Palette.ts에 세팅해줬습니다.
팔레트는 컴포넌트에서 직접적으로 참조되지 않기 때문에 JS 객체로 만들어줬습니다.

// src/tokens/color/Palette.ts

export const palette = {
  common: {
    0: '#000000',
    100: '#FFFFFF',
  },
  neutral: {
    0: '#000000',
    5: '#0F0F0F',
    10: '#171717',
    15: '#1C1C1C',
    20: '#2A2A2A',
    22: '#303030',
    30: '#474747',
    40: '#5C5C5C',
    50: '#737373',
    60: '#8A8A8A',
    70: '#9B9B9B',
    80: '#B0B0B0',
    90: '#C4C4C4',
    95: '#DCDCDC',
    99: '#F7F7F7',
    100: '#FFFFFF',
  },
  coolNeutral: {
    0: '#000000',
    5: '#0F0F10',
    7: '#141415',
    10: '#171719',
    15: '#1B1C1E',
    17: '#212225',
    20: '#292A2D',
    22: '#2E2F33',
    23: '#333438',
    25: '#37383C',
    30: '#46474C',
    40: '#5A5C63',
    50: '#70737C',
    60: '#878A93',
    70: '#989BA2',
    80: '#AEB0B6',
    90: '#C2C4C8',
    95: '#DBDCDF',
    96: '#E1E2E4',
    97: '#EAEBEC',
    98: '#F4F4F5',
    99: '#F7F7F8',
    100: '#FFFFFF',
  },
  red: {
    0: '#000000',
    10: '#3B0101',
    20: '#730303',
    30: '#B00C0C',
    40: '#E52222',
    50: '#FF4242',
    60: '#FF6363',
    70: '#FF8C8C',
    80: '#FFB5B5',
    90: '#FED5D5',
    99: '#FFFAFA',
    100: '#FFFFFF',
  },
  redOrange: {
    0: '#000000',
    10: '#290F00',
    20: '#592100',
    30: '#913500',
    40: '#C94A00',
    48: '#F55A00',
    50: '#FF5E00',
    60: '#FF7B2E',
    70: '#FF9B61',
    80: '#FFBD96',
    90: '#FED9C4',
    95: '#FEEEE5',
    99: '#FFFAF7',
    100: '#FFFFFF',
  },
  orange: {
    0: '#000000',
    10: '#361E00',
    20: '#663A00',
    30: '#9C5800',
    39: '#D17600',
    40: '#D47800',
    50: '#FF9200',
    60: '#FFA938',
    70: '#FFC06E',
    80: '#FFD49C',
    90: '#FEE6C6',
    95: '#FEF4E6',
    99: '#FFFCF7',
    100: '#FFFFFF',
  },
  lime: {
    0: '#000000',
    10: '#112900',
    20: '#225200',
    30: '#347D00',
    37: '#429E00',
    40: '#48AD00',
    50: '#58CF04',
    60: '#6BE016',
    70: '#88F03E',
    80: '#AEF779',
    90: '#CCFCA9',
    95: '#E6FFD4',
    99: '#F8FFF2',
    100: '#FFFFFF',
  },
  green: {
    0: '#000000',
    10: '#00240C',
    20: '#004517',
    30: '#006E25',
    40: '#009632',
    50: '#00BF40',
    60: '#1ED45A',
    70: '#49E57D',
    80: '#7DF5A5',
    90: '#ACFCC7',
    95: '#D9FFE6',
    99: '#F2FFF6',
    100: '#FFFFFF',
  },
  cyan: {
    0: '#000000',
    10: '#00252B',
    20: '#004854',
    30: '#006F82',
    40: '#0098B2',
    50: '#00BDDE',
    60: '#28D0ED',
    70: '#57DFF7',
    80: '#8AEDFF',
    90: '#B5F4FF',
    95: '#DEFAFF',
    99: '#F7FEFF',
    100: '#FFFFFF',
  },
  lightBlue: {
    0: '#000000',
    10: '#002130',
    20: '#004261',
    30: '#006796',
    40: '#008DCF',
    50: '#00AEFF',
    60: '#3DC2FF',
    70: '#70D2FF',
    80: '#A1E1FF',
    90: '#C4ECFE',
    95: '#E5F6FE',
    99: '#F7FDFF',
    100: '#FFFFFF',
  },
  blue: {
    0: '#000000',
    10: '#001536',
    20: '#002966',
    30: '#003E9C',
    40: '#0054D1',
    45: '#005EEB',
    50: '#0066FF',
    55: '#1A75FF',
    60: '#3385FF',
    65: '#4F95FF',
    70: '#69A5FF',
    80: '#9EC5FF',
    90: '#C9DEFE',
    95: '#EAF2FE',
    99: '#F7FBFF',
    100: '#FFFFFF',
  },
  violet: {
    0: '#000000',
    10: '#11024D',
    20: '#23098F',
    30: '#3A16C9',
    40: '#4F29E5',
    45: '#5B37ED',
    50: '#6541F2',
    60: '#7D5EF7',
    70: '#9E86FC',
    80: '#C0B0FF',
    90: '#DBD3FE',
    95: '#F0ECFE',
    99: '#FBFAFF',
    100: '#FFFFFF',
  },
  purple: {
    0: '#000000',
    10: '#290247',
    20: '#580A7D',
    30: '#861CB8',
    40: '#AD36E3',
    50: '#CB59FF',
    60: '#D478FF',
    70: '#DE96FF',
    80: '#E9BAFF',
    90: '#F2D6FF',
    95: '#F9EDFF',
    99: '#FEFBFF',
    100: '#FFFFFF',
  },
  pink: {
    0: '#000000',
    10: '#3D0133',
    20: '#730560',
    30: '#A81690',
    40: '#D331B8',
    46: '#E846CD',
    50: '#F553DA',
    60: '#FA73E3',
    70: '#FF94ED',
    80: '#FFB8F3',
    90: '#FED3F7',
    95: '#FEECFB',
    99: '#FFFAFE',
    100: '#FFFFFF',
  },
} as const;

Semantic 세팅

Semantic 색상은ㄹ Vanilla Extract의 createGlobalTheme를 이용해 설정해줬습니다.

// src/tokens/color/Semantic.css.ts

import { createGlobalTheme } from '@vanilla-extract/css';
import { palette } from './Palette';

const withAlpha = (hex: string, alpha: number) => {
  return `color-mix(in srgb, ${hex} ${alpha}%, transparent)`;
};

export const semantic = createGlobalTheme(':root', {
  primary: {
    normal: palette.blue[50],
    strong: palette.blue[45],
    heavy: palette.blue[40],
  },
  label: {
    normal: palette.coolNeutral[10],
    strong: palette.coolNeutral[0],
    neutral: withAlpha(palette.coolNeutral[22], 88),
    alternative: withAlpha(palette.coolNeutral[25], 61),
    assistive: withAlpha(palette.coolNeutral[25], 28),
    disable: withAlpha(palette.coolNeutral[25], 16),
  },
  background: {
    normal: {
      normal: palette.coolNeutral[100],
      alternative: palette.coolNeutral[99],
    },
    elevated: {
      normal: palette.coolNeutral[100],
      alternative: palette.coolNeutral[99],
    },
  },
  interaction: {
    inactive: palette.coolNeutral[70],
    disable: palette.coolNeutral[98],
  },
  line: {
    normal: {
      normal: withAlpha(palette.coolNeutral[50], 22),
      neutral: withAlpha(palette.coolNeutral[50], 16),
      alternative: withAlpha(palette.coolNeutral[50], 8),
      strong: withAlpha(palette.coolNeutral[50], 52),
    },
    solid: {
      normal: palette.coolNeutral[96],
      neutral: palette.coolNeutral[97],
      alternative: palette.coolNeutral[98],
      strong: palette.coolNeutral[80],
    },
  },
  fill: {
    normal: withAlpha(palette.coolNeutral[50], 8),
    strong: withAlpha(palette.coolNeutral[50], 16),
    alternative: withAlpha(palette.coolNeutral[50], 5),
  },
  static: {
    white: palette.common[100],
    black: palette.common[0],
  },
  accent: {
    background: {
      redOrange: palette.redOrange[50],
      lime: palette.lime[50],
      cyan: palette.cyan[50],
      lightBlue: palette.lightBlue[50],
      violet: palette.violet[50],
      purple: palette.purple[50],
      pink: palette.pink[50],
    },
    foreground: {
      red: palette.red[40],
      redOrange: palette.redOrange[48],
      orange: palette.orange[39],
      lime: palette.lime[37],
      green: palette.green[40],
      cyan: palette.cyan[40],
      lightBlue: palette.lightBlue[40],
      blue: palette.blue[45],
      violet: palette.violet[45],
      purple: palette.purple[40],
      pink: palette.pink[46],
    },
  },
  material: {
    dimmer: withAlpha(palette.coolNeutral[10], 52),
  },
  inverse: {
    primary: palette.blue[60],
    background: palette.coolNeutral[15],
    label: palette.coolNeutral[99],
  },
});

다음에는 텍스트 크기 등 토큰들을 설정하고, Vanilla Extract의 Recipe 패키지를 이용해 컴포넌트를 하나 만들어보려고 합니다.