Skip to content

Commit a456045

Browse files
authored
Design 토큰 파싱 동작 수정 및 토큰 생성 (#14)
* feat: 스토리북 초기 설정 * chore: 로컬 환경 설정 gitignore에 추가 * feat: 디자인 토큰 tailwind 적용 설정 * feat: 스토리북 배포용 공용 컴포넌트 설정 * feat: tailwind설정에 postcss관련 설정 임시 복원 및 storybook 배포 설정 * feat: 스토리북 배포 관련 설정 추가 * feat: 디자인 시스템 스토리북 초기 및 테스트용 설정 * feat: 프리티어 및 린트 설치 및 설정 (임시) * style: 린트 및 프리티어로 인한 코드 스타일 변경 * feat: 디자인 시스템 스토리북 배포 설정 수정 포크한 레포에 작동 테스틀 위해 연결 스토리북 형태도 세팅함 * feat: token 변환 설정파일 수정 구조 수정 및 tailwind prefix에 맞게 mapping * docs: 디자인 시스템 관련 리드미 템플릿 수정 * feat: 디자인 시스템 패키지 배포 테스트 성공 * chore: tailwind/postcss 버전 복구 * feat: 스토리북 스타일 autodocs처리 * docs: 디자인 시스템 관련 문서들 정리(임시) * feat: 토큰 설정 및 스토리북 배포 설정 수정 * feat: 빌드 관련 tailwindcss/postcss 버전 수정 및 gitignore 포함 이전 패키지 버전에선 빌드가 안 됐음. * feat: ci linux환경에서의 스토리북 빌드 관련 패키지 설정 수정 * Merge branch 'design' into main * feat: 디자인 시스템 스토리북 예시 수정 * feat: zustand설치 * feat: 상현 개인 레포에서 스토리북 배포 동작하도록 수정 vercel 정책 상 prography계정의 레포는 organization이라 유료 플랜이라. * feat: deploy-storybook path에 자기자신 포함해, 변경 시 동작하도록 수정 * fix: deploy-storybook path경로 수정 마이너 수정이라 main에서 진행 * feat: Chromatic UI 테스팅 github action 실험 적용 * feat: chromatic 설치 * feat: chromatic ci 관련 yarn->npm으로 변경 * feat: chromatic 실험용 Test 컴폰너트 ui 변경 * feat: chromatic github action 패키지 버전 수정 * feat: chromatic ci 중단 옵션 수정 * feat: upstream PR에 대해 작동하도록 수정 * feat: 크로마틱 연동 테스트 * feat: 스토리북 plop통한 템플릿 생성 기능 추가 * docs: 스토리북 Intro 문서 수정 * feat: 크로마틱 연동 upstream에 적용하도록 수정 * docs: 스토리북 Intro 문구 수정 code형태 아니어야 했기에. * docs: 스토리북 intro 스타일 다듬기 * docs: 스토리북 버전 및 change log관련 문구 수정 * feat: 스토리북 배포 주소 추가 * docs: 스토리북 intro 문서 스타일 수정. 숫자 표기 안되는 문제로 인해. * docs: 프로젝트 README에 디자인시스템 배포 페이지 추가 * docs: 스토리북 Intro 스타일 수정 * docs: 프로젝트 README에 디자인시스템 배포 페이지 추가 * fix: 디자인 시스템 chromatic 연결 프로젝트 변경 다른 프로젝트랑 연결 되어 있었기에 수정. * feat: chromatic github action에서 pull request target 방식으로 수정 forked에서의 pull request로는 secret을 사용할 수 없기 때문에. * feat: 디자인 토큰 새로운 형식 대해 파싱 수정 파싱되지 않던 형식 처리, tailwind에선 사용되지 않는 토큰 제거, tailwind prefix 매핑 수정. * feat: 수정된 디자인 토큰 파싱으로 tailwind 토큰 생성 * fix: github action 관련 chromatic 액션 버전 수정
1 parent fdba8e8 commit a456045

File tree

4 files changed

+187
-26
lines changed

4 files changed

+187
-26
lines changed

.github/workflows/chromatic.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ jobs:
4040
run: npm run build-storybook # 또는 npm run build-storybook
4141

4242
- name: Run Chromatic
43-
uses: chromaui/action@12.2.0
43+
uses: chromaui/action@v1
4444
with:
4545
# 👇 Chromatic 프로젝트 토큰 (Secrets에 저장 권장)
4646
projectToken: ${{ secrets.CHROMATIC_PROJECT_TOKEN }}

app/tokens.css

Lines changed: 73 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,74 @@
11
@theme {
2-
}
2+
--radius-2: 0.125rem;
3+
--radius-4: 0.25rem;
4+
--radius-8: 0.5rem;
5+
--radius-12: 0.75rem;
6+
--radius-16: 1rem;
7+
--color-label-inverse: #ffffff;
8+
--color-label-normal: #33363d;
9+
--color-label-strong: #1e2124;
10+
--color-label-alternative: #464c53;
11+
--color-label-primary: #5d5fef;
12+
--color-label-disabled: #8a949e;
13+
--color-label-assistive: #6d7882;
14+
--color-background-normal: #f7f7f8;
15+
--color-background-strong: #33363d;
16+
--color-background-primary: #5d5fef;
17+
--color-background-alternative: #e6e8ea;
18+
--color-background-disabled: #b1b8be;
19+
--color-status-negative: #ea3429;
20+
--color-status-positive: #228738;
21+
--spacing-gap-2: 0.125rem;
22+
--spacing-gap-4: 0.25rem;
23+
--spacing-gap-8: 0.5rem;
24+
--spacing-gap-12: 0.75rem;
25+
--spacing-gap-16: 1rem;
26+
--spacing-gap-20: 1.25rem;
27+
--spacing-padding-2: 0.125rem;
28+
--spacing-padding-4: 0.25rem;
29+
--spacing-padding-8: 0.5rem;
30+
--spacing-padding-12: 0.75rem;
31+
--spacing-padding-16: 1rem;
32+
--spacing-padding-20: 1.25rem;
33+
--radius-round: 62.438rem;
34+
--border-normal: 0.062rem solid #cdd1d5;
35+
--font-fontFamilies-suit-variable: SUIT Variable;
36+
--leading-lineHeights-0: 140%;
37+
--leading-lineHeights-1: 120%;
38+
--leading-lineHeights-2: 140%;
39+
--leading-lineHeights-3: 140%;
40+
--leading-lineHeights-4: 140%;
41+
--leading-lineHeights-5: 120%;
42+
--leading-lineHeights-6: 120%;
43+
--leading-lineHeights-7: 140%;
44+
--font-weight-fontWeights-suit-variable-0: Bold;
45+
--font-weight-fontWeights-suit-variable-1: Regular;
46+
--font-weight-fontWeights-suit-variable-2: Medium;
47+
--text-fontSize-0: 24;
48+
--text-fontSize-1: 16;
49+
--text-fontSize-2: 16;
50+
--text-fontSize-3: 14;
51+
--text-fontSize-4: 14;
52+
--text-fontSize-5: 20;
53+
--text-fontSize-6: 20;
54+
--text-fontSize-7: 12;
55+
--tracking-letterSpacing-0: -1%;
56+
--tracking-letterSpacing-1: -1%;
57+
--tracking-letterSpacing-2: -1%;
58+
--tracking-letterSpacing-3: -1%;
59+
--tracking-letterSpacing-4: -1%;
60+
--tracking-letterSpacing-5: -1%;
61+
--tracking-letterSpacing-6: -1%;
62+
--tracking-letterSpacing-7: -1%;
63+
--non-mapped-paragraphSpacing-0: 0;
64+
--non-mapped-paragraphSpacing-1: 0;
65+
--non-mapped-paragraphSpacing-2: 0;
66+
--non-mapped-paragraphSpacing-3: 0;
67+
--non-mapped-paragraphSpacing-4: 0;
68+
--non-mapped-paragraphSpacing-5: 0;
69+
--non-mapped-paragraphSpacing-6: 0;
70+
--non-mapped-paragraphSpacing-7: 0;
71+
--non-mapped-textCase-none: none;
72+
--non-mapped-textDecoration-none: none;
73+
--spacing-paragraphIndent-0: 0px;
74+
}

sd-tokens.config.mjs

Lines changed: 111 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,128 @@
11
import StyleDictionary from "style-dictionary";
2+
import { usesReferences } from "style-dictionary/utils";
23

4+
/**
5+
* tailwind에서 사용되는 prefix 매핑
6+
*/
37
const token2TailwindTypeMap = {
48
color: "color",
5-
sizing: "dimension",
6-
spacing: "dimension",
7-
dimension: "dimension",
8-
borderWidth: "border-witdh",
9-
borderRadius: "radius",
10-
border: "color",
9+
sizing: "spacing",
10+
spacing: "spacing",
11+
dimension: "spacing",
12+
// border는 합쳐져서 오기 때문에 다르게 처리해야 함.
13+
borderWidth: "border-witdh", // 얘는 일단 없어져야함.
14+
borderRadius: "radius", // 얘는 따로임.
15+
border: "border",
16+
//
1117
opacity: "opacity",
1218
boxShadow: "shadow",
19+
// 폰트도 체크해볼 것.
1320
fontFamilies: "font",
1421
fontWeights: "font-weight",
1522
lineHeights: "leading",
16-
fontSizes: "font-size",
23+
fontSizes: "text",
1724
letterSpacing: "tracking",
25+
26+
// paragraphSpacing는 token type에 존재는 하지만 값을 0으로 해 안쓰는 듯. tailwind엔 없음.
1827
};
1928

20-
// 커스텀 포맷 등록
29+
/**
30+
* 파싱에서 아예 제외시킬 토큰들.
31+
* tailwind에서 사용되지 않으면서 에러를 일으키는 경우들.
32+
* EX)
33+
* semantic의 토큰을 참조값으로 사용하는 semantic 토큰의 경우
34+
*/
35+
const excludingTokenNames = ["title", "body", "caption"];
36+
37+
/**
38+
* tailwind에서 사용할 수 있도록 formatting
39+
*/
2140
StyleDictionary.registerFormat({
2241
name: "css/theme-variables",
2342

2443
format: function ({ dictionary }) {
2544
return [
2645
"@theme {",
27-
...dictionary.allTokens.map(
28-
(prop) =>
29-
` --${token2TailwindTypeMap?.[prop.type] ?? "non-mapped"}-${prop.name}: ${prop.value};`,
30-
),
46+
...dictionary.allTokens
47+
.filter((prop) => !prop.name.includes("primitive"))
48+
.map((prop) => {
49+
//test
50+
console.log("prop.name, prop.type: ", prop.name, prop.type);
51+
const nameFromPath = prop.path.slice(1).join("-");
52+
53+
return ` --${token2TailwindTypeMap?.[prop.type] ?? "non-mapped"}-${nameFromPath}: ${prop.value};`;
54+
}),
3155
"}",
3256
].join("\n");
3357
},
3458
});
3559

60+
/**
61+
* 참조값을 사용하는 토큰들에 대해 처리.
62+
* 피참조값은 Primitive로 가정함.
63+
*/
64+
StyleDictionary.registerTransform({
65+
name: "value/cssVarRef",
66+
type: "value",
67+
transitive: true,
68+
filter: function (token) {
69+
// 이 토큰이 다른 토큰을 참조하는지 확인합니다.
70+
const filterRes =
71+
typeof token.original.value === "string" &&
72+
token.original.value.startsWith("{") &&
73+
token.original.value.endsWith("}");
74+
75+
return filterRes;
76+
},
77+
transform: function (token, options) {
78+
const originalValue = token.original.value;
79+
if (usesReferences(originalValue)) return undefined;
80+
81+
throw new Error("transform 내부 transform defer 에러");
82+
},
83+
});
84+
85+
/**
86+
* 아래는 사용될 토큰들에 대해 Semantic에서의 참조값은 Primitive의 것으로
87+
* 참조 경로 재구성하는 작업.
88+
*/
89+
90+
const convertRef = (stringValue, setName) => {
91+
if (stringValue.startsWith("{"))
92+
// 참조인 "{","}"내부에 setName추가
93+
return `{${setName}.${stringValue.slice(1, -1)}}`;
94+
95+
// 참조가 아니라면
96+
return stringValue;
97+
};
98+
3699
const recursliveParsingHelper = (setName, curKey, curValue) => {
37100
// 종료 조건
38101
if (Object.keys(curValue).includes("type")) {
39-
const prevValueHandled = curValue.value.slice(1, -1);
40-
return { ...curValue, value: `{${setName}.${prevValueHandled}}` };
102+
const newValue =
103+
typeof curValue.value === "string"
104+
? convertRef(curValue.value, setName)
105+
: // object인 경우
106+
Object.entries(curValue.value).reduce(
107+
(acc, [tokenEleKey, tokenELeValue]) => {
108+
if (tokenELeValue.startsWith("{"))
109+
return {
110+
...acc,
111+
[tokenEleKey]: convertRef(tokenELeValue, setName),
112+
};
113+
return { ...acc, [tokenEleKey]: tokenELeValue };
114+
},
115+
{},
116+
);
117+
return {
118+
[curKey]: { ...curValue, value: newValue },
119+
};
41120
}
42121

43122
const resultValue = Object.entries(curValue).reduce(
44123
(acc, [nextKey, innerObj]) => {
45-
const resValue = recursliveParsingHelper(setName, nextKey, innerObj);
46-
return { ...acc, [nextKey]: resValue };
124+
const resToken = recursliveParsingHelper(setName, nextKey, innerObj);
125+
return { ...acc, ...resToken };
47126
},
48127
{},
49128
);
@@ -58,22 +137,29 @@ StyleDictionary.registerParser({
58137

59138
const convertedParsed = Object.entries(parsed).reduce(
60139
(accAllTokens, [setName, tokens]) => {
61-
if (setName.startsWith("Primitive") || setName.startsWith("$"))
140+
if (setName.startsWith("Primitive") || setName.startsWith("$")) {
62141
return { ...accAllTokens, [setName]: tokens };
142+
}
63143

64-
const primitiveSet = setName.replace("Semantic", "Primitive");
144+
const primitiveTargetSet = setName.replace("Semantic", "Primitive");
65145

66146
const semanticTokens = Object.entries(tokens).reduce(
67147
(accSemanticTokens, [key, value]) => {
148+
// 제외시킬 토큰은 파싱 제외.
149+
if (excludingTokenNames.includes(key))
150+
return { ...accSemanticTokens };
151+
68152
const newSemanticTokens = recursliveParsingHelper(
69-
primitiveSet,
153+
primitiveTargetSet,
70154
key,
71155
value,
72156
);
157+
73158
return { ...accSemanticTokens, ...newSemanticTokens };
74159
},
75160
{},
76161
);
162+
77163
return { ...accAllTokens, [setName]: semanticTokens };
78164
},
79165
{},
@@ -83,13 +169,19 @@ StyleDictionary.registerParser({
83169
},
84170
});
85171

172+
/**
173+
* 토큰 처리 설정
174+
*/
175+
86176
export default {
87177
source: ["tokens/**/*.json"],
88178

89179
parsers: ["json-parser"],
90180
platforms: {
91181
css: {
92182
transformGroup: "css",
183+
184+
transforms: ["value/cssVarRef"],
93185
buildPath: "app/", //변환한 파일을 저장할 경로
94186
files: [
95187
{

tokens/design-tokens.json

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -803,9 +803,6 @@
803803
},
804804
"$themes": [],
805805
"$metadata": {
806-
"tokenSetOrder": [
807-
"Primitive/light",
808-
"Semantic/light"
809-
]
806+
"tokenSetOrder": ["Primitive/light", "Semantic/light"]
810807
}
811-
}
808+
}

0 commit comments

Comments
 (0)