어제 수집한 토큰을 바탕으로 색상 CSS 변수를 세팅해줬습니다.
세팅하기 전에 먼저 https://po4tion.dev/biome 를 참고해 프로젝트에 Biome를 세팅해줍니다.
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 색상은ㄹ 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 패키지를 이용해 컴포넌트를 하나 만들어보려고 합니다.