회사에서 Figma에서 Token Studio for Figma(Figma Tokens)
(*이하 토큰 스튜디오) 플러그인을 사용해서
디자인 토큰을 생성하면 TailwindCSS에서 전달받은 토큰을 적용해야 하는 이슈가 있었다.
토큰 스튜디오에서 만들어준 json 파일을 보고 tailwind.config.js 파일에 하나씩 추가하는 방법으로
해결하려 했으나 토큰의 갯수가 적은 것도 아니였고, 오타가 발생할 위험도 있었고 수정이 발생할 때마다
수정된 부분을 찾아야하는 유지보수성도 매우 안좋은 방법이라 생각했다.
때문에 한 번에 토큰 스튜디오에서 만든 디자인 토큰을 tailwindCSS에서 사용할 수 있는 방법을 찾고 싶었다.
이것 저것 찾아보다 토큰 스튜디오에서 만든 라이브러리와 비슷한 고민(?)을 한 개발자분이 만드신 라이브러리를 사용해서
해결 방법을 찾을 수 있었다.
새로운 tailwind.config.js을 생성해서 기존 파일을 덮어쓰는 방식으로 진행합니다.
yarn add style-dictionary
yarn add @tokens-studio/sd-transforms
yarn add sd-tailwindcss-transformer
토큰 스튜디오 에서 생성한 디자인 토큰을 .json
파일로 export할 수 있다.
프런트엔드 개발자는 json 파일을 사용해서 프로젝트에 디자인 토큰을 적용해야 한다. 하지만 토큰 스튜디오에서 만들어주는 json 파일을 확인해보면 다음과 같은 형태임을 확인할 수 있다.
{
...
"borderRadius": {
"sm": {
"value": "4",
"type": "borderRadius"
},
"lg": {
"value": "8",
"type": "borderRadius"
},
"xl": {
"value": "16",
"type": "borderRadius"
},
"multi-value": {
"value": "{borderRadius.sm} {borderRadius.lg}",
"type": "borderRadius",
"description": "You can have multiple values in a single radius token. Read more on these: https://docs.tokens.studio/available-tokens/border-radius-tokens#single--multiple-values"
}
},
...
}
이걸 바로 tailwind에서 적용할 수 없기 때문에 이 토큰을 tailwind.config.js 파일로 변환해주는 작업이 필요하다.
그 작업을 위해서 Style Dictionary
라이브러리를 사용한다.
문제는 Style-Dictionary에서 json 파일을 CSS로 변환하는 포맷은 지원하는데
tailwindCSS로 변환하는 포맷은 지원하지 않는다.
css, scss, less, stylus, javascript, typescript, android, compose, ios, json, sketch, flutter 등 지원
때문에 Style Dictionary와 더불어서 sd-tailwindcss-transformer
라이브러리도 사용해야 한다
그러면 tailwind.config.js 파일에 맞게 json 파일을 변환해 준다.
sd-tailwind-transformer 공식문서에서 제공하는 예제를 바탕으로 변환하는 코드를 만들어본다.
파일 이름은 build-tw.js
(다른 이름이여도 상관없음.)으로 만들고 파일의 위치는 프로젝트 최상단에 둔다. (위치도 상관 없음.)
const StyleDictionaryModule = require("style-dictionary");
const { makeSdTailwindConifg } = require("sd-tailwindcss-transformer");
const StyleDictionary = StyleDictionaryModule.extend(
makeSdTailwindConfig({
type: "all",
source: ["tokens.json"], // 토큰 스튜디오에서 만들어준 json 파일 경로
buildPath: ""
})
);
StyleDictionary.buildAllPlatforms();
node 명령어로 build-tw.js를 실행한다.
node build-tw.js
에러가 없다면 tailwind.config.js 파일이 변경된 것을 확인할 수 있는데
그대로 바로 사용할 수 있는지 확인해보면
/** @type {import('tailwindcss').Config} */
module.exports = {
mode: "jit",
content: ["./src/**/*.{ts,tsx}"],
darkMode: "class",
theme: {
extend: {
dimension: {
scale: "2",
xs: "4",
sm: "4 * 2",
md: "4 * 2 * 2",
lg: "4 * 2 * 2 * 2",
xl: "4 * 2 * 2 * 2 * 2"
},
// ... more ...
}
}
}
scale의 값에 px 또는 rem 같은 단위도 없고 sm 부터는 "4 * 2" 라는 스트링 값이 들어가게 된다.
<div className="text-sm">Hello</div>
이렇게 tailwind에서 적용한다면 오류가 발생하게 된다.
토큰 스튜디오의 토큰을 tailwind.config.js 파일로 바로 만들어주는 방법은 맞지만 후처리 작업이 필요해 보인다.
때문에 본래 찾고자 했던, 한 번에 tailwind.config.js로 변환해주는 방법이라고는 볼 수 없다.
먼저 문제의 원인을 밝히자면
토큰 스튜디오에서 export 한 json 파일을 sd에 바로 사용한게 문제다. 이것 때문인지는 모르겠으나
토큰 스튜디오에서 라이브러리를 만들었는데 그게 바로 @tokens-studio/sd-transforms 라이브러리다.
이 라이브러리의 핵심 역할이라면, px 같은 사이즈 단위를 붙여주고 계산된 값으로 사용할 수 있게 해준다.
결과로 비교해보면
먼저 토큰 스튜디오에서 만들어주는 json 파일 원본이다.
{
"borderRadius": {
"sm": {
"value": "4",
"type": "borderRadius"
},
"lg": {
"value": "8",
"type": "borderRadius"
},
"xl": {
"value": "16",
"type": "borderRadius"
},
"multi-value": {
"value": "{borderRadius.sm} {borderRadius.lg}",
"type": "borderRadius",
"description": "You can have multiple values in a single radius token. Read more on these: https://docs.tokens.studio/available-tokens/border-radius-tokens#single--multiple-values"
}
},
...
}
그리고 한 번 더 변환했을 때의 결과는
"borderRadius": {
"sm": {
"value": "4px",
"type": "borderRadius",
"filePath": "tokens.json",
"isSource": true,
"original": {
"value": "4",
"type": "borderRadius",
"filePath": "tokens.json",
"isSource": true
},
"name": "borderRadiusSm",
"attributes": {},
"path": [
"borderRadius",
"sm"
]
},
...
},
변환하기 위해서 스크립트 파일을 하나 생성한다. 이름과 파일의 위치는 상관없다. build-ts.js
라는 이름으로 최상위 경로에 생성한다.
원본 json 파일이 아닌 한번 변환된 json 파일을 사용한다.
const { registerTransforms } = require("@tokens-studio/sd-transforms");
const StyleDictionary = require("style-dictionary");
registerTransforms(StyleDictionary);
const sd = StyleDictionary.extend({
source: ["tokens.json"],
platforms: {
tailwind: {
transformGroup: "tokens-studio",
buildPath: "",
files: [
{
destination: "tokens.json",
format: "json",
},
],
},
},
});
sd.cleanAllPlatforms();
sd.buildAllPlatforms();
source의 원본 파일의 경로, destination에는 출력 파일의 이름을 작성하면 된다.
platforms, transformGroup 에 대한 자세한 정보는 라이브러리를 참조하기 바란다.
Style Dictionary가 단순히 Figma와 TailwindCSS를 위해서 존재하는게 아니기 때문에 정말 다양한 옵션들이 많이 있다. 때문에 한번쯤 공식 문서를 확인하길 바란다.
그렇다면 이제 다시 sd-tailwindcss-transformer
라이브러리로 변환을 해볼 차례다
이전에 만들어둔 build-tw.js
파일을 사용한다.
node build-tw.js // 토큰 스튜디오 라이브러리로 json 파일 변환
node build-ts.js // 변환된 json 파일로 tailwind.config.js 파일 생성
두 단계를 모두 정상적으로 실행했다면 이전 처럼 tailwind.config.js 파일이 생성되었을 텐데
이전과 다른 점을 볼 수 있을것이다.
/** @type {import('tailwindcss').Config} */
module.exports = {
mode: "jit",
content: ["./src/**/*.{ts,tsx}"],
darkMode: "class",
theme: {
extend: {
dimension: {
scale: "2px",
xs: "4px", // before "4 * 2"
sm: "8px",
md: "16px",
lg: "32px",
xl: "64px"
},
// ... more ...
}
}
}
이전과 다르게 바로 tailwindCSS에서 적용할 수 있게 되었다.
방법을 찾기위해 여러가지 시도했던 내용들을 글로 남기다보니 순서가 헷갈릴 수 있어서 마지막으로 정리를 해본다.
Figma에서 tokens-studio 플러그인을 사용해서 tokens.json를 export 한다.
이 tokens.json을 @tokens-studio/sd-transforms
라이브러리를 사용해서 tokens을 한번 변환해준다.
변환된 tokens.json을 sd-tailwindcss-transformer
라이브러리를 사용해서 tailwind.config.js 파일로 변환한다.
tailwind CSS 2.x 버전때 config 파일을 만들어주는 것으로 보인다. "jit" mode, darkMode 설정은 tailwind 2.X 버전 때 공식문서에서 볼 수 있고 3.X 버전으로 설치하면 나오지 않는 내용들이다. 물론 3.X 버전에서 사용할 때 문제가 발생할 것으로 보이지는 않는다.