本系列文章會在筆者的部落格繼續連載!Design System 101 感謝大家的閱讀!
HiHi! 中秋愉快!
在上面的篇章,我們提到了 style dictionary 的概念,以及如何運用它來管理視覺元素,而大家還記得先前提到從 figma 到 css 整個實踐的架構圖嗎?
沒錯!今天我們就要來實踐整個架構,而以下會是整個實踐的流程:
本篇將加入 design-tokens
這個 package,而從系列的第一篇文章至今,整體的 Design System 結構會是這樣:
design-system
├── README.md
├── package.json
├── pnpm-lock.yaml
├── packages
│ ├── components
| | ├── focus-scope
| | |── visually-hidden
│ └── tsconfig
| |── design-tokens <-- new
...
首先在 packages
下新增一個 design-tokens
的資料夾,並且初始化 packages.json。
design-system > mkdir design-tokens
design-system > cd design-tokens
design-system > pnpm init
在 design-tokens
專案下安裝以下套件:
pnpm add style-dictionary sass postcss stylelint stylelint-config-prettier stylelint-config-standard stylelint-config-standard-scss stylelint-order stylelint-prettier -D
在 design-tokens
的根目錄底下建立 stylelintrc.json
design-system > touch stylelintrc.json
可以根據喜好設定 Stylelint,這是筆者的設定檔。
這次筆者會以 Material Design 的視覺元素與組件設計檔來作為 Design System 的基底。
Material Design 將 Design Token 切分成三個層級,分別為 Reference Token, System Token 以及最底層的 Component Token。
每一層的關係都在之前提過,可以參考 Design System 101 - Design Token,這裡就不在贅述。
由於 Material Design 將 Token 切分成三個層級,第一個問題就是要先定義哪一層級的 Token 需要納入 design-token 這個 packages 中管理?
在目前的架構中,筆者會將 Reference Token 與 System Token 納入 design-token,而 Component Token 則是放在各個組件中。
這也是現今許多 Design System 的做法,如 Pinterest 的 Gestalt 或是 Shopify 的 Polaris 等等。
接下來要將 Material Design 的視覺元素轉換成 key-value pair 的形式,這裡會以 color
作為範例,而以下是 design-tokens 的結構:
design-tokens
├── README.md
├── package.json
├── pnpm-lock.yaml
├── tokens
│ ├── color
│ | ├── base.json <--- Reference Token
│ | ├── alias.json <-- System Token
...
我們會將 Reference Token 與 System Token 分別存放在 base.json
與 alias.json
,而在 alias.json
內的值則會參照 base.json
。
這也呼應了前面所提到的一致性,當設計師或是當今天想要 rebrand,就只需要更改 Reference Token 的值,而不需要更改所有的 Design Token。
在 Material Design 中 (如上圖),可以看到所有 Reference Token 這是最上層也是最抽象的,而將其轉換成 Token 就會如下:
{
"ref": {
"palette": {
"primary": {
"0": { "value": "#000000" },
"10": { "value": "#21005D" },
...
"100": { "value": "#FFFFFF" }
},
"secondary": {
"0": { "value": "#000000" },
"10": { "value": "#1D192B" },
...
"100": { "value": "#FFFFFF" }
},
}
}
}
System Token 相較於 Reference Token 會有更明確的定義,例如 --sys-color-primary-container
可以清楚知道這是 primary 的顏色,且是用在 container 上。
大部分的 System Token 其背後都會有對應的 Reference Token,在 color 中便是如此:
{
"sys": {
"color": {
"primary": {
"light": { "value": "{ref.palette.primary.40.value}" },
},
"primary-container": {
"light": { "value": "{ref.palette.primary.90.value}" },
}
}
...
}
}
也可以定義該 System Token 在 dark mode 中的值
{
"sys": {
"color": {
"primary": {
"light": { "value": "{ref.palette.primary.40.value}" },
"dark": { "value": "{ref.palette.primary.80.value}" }
},
"primary-container": {
"light": { "value": "{ref.palette.primary.90.value}" },
"dark": { "value": "{ref.palette.primary.30.value}" }
}
}
...
}
}
當然視覺元素不會只有顏色,也會有字體、間距等等,其概念都是一樣的,這裡就不再一一贅述,可以參考筆者的 design-tokens。
最後在透過 style-dictionary 來產生不同平台的 Styling,而其會需要一個 config.js
來定義所有建置邏輯。
style-dictionary 還有另一個優點就是可以透過一些客製化的 script 來對其進行擴充,先來介紹最基本的用法。
{
"source": ['./tokens/**/*.json'],
"platforms": {
"css": {
"transformGroup": "css",
"buildPath": "dist/css/",
"files": [
{
"destination": "_variables.css",
"format": "css/variables"
}
]
},
"js": {
"transformGroup": "js",
"buildPath": "dist/js/",
"files": [
{
"destination": "variables.js",
"format": "javascript/es6"
}
]
}
}
}
首先 source
是用來定義要轉換的檔案,像是上面的例子,我們會將所有的 token 都放在 tokens
底下,所以就可以設定 source
為 ./tokens/**/*.json
接下來就是 platforms
,這裡會定義要轉換成哪些平台,像是 CSS、JS 等等,而每個平台都會有 transformGroup
與 files
,可以參考 style-dictionary 的文檔。
而以下是筆者的設定
transformGroup
與 files
。dist/normalize/normalize.css
。這個好處是可以把一些基本的 CSS 與 Design Token 的 CSS 整理成一個檔案,而在引用的時候就可以直接引用 normalize.css
。
最後,有了屬於自己 Design System 的 normalize.css
之後,就可以在專案中引入它,並且使用 Design Token 來進行開發了!
https://codesandbox.io/embed/cranky-meitner-nvynmh?fontsize=14&hidenavigation=1&theme=dark
可以嘗試將 light
改成 dark
來看看效果!
document.documentElement.setAttribute('data-theme', 'light');