iT邦幫忙

2023 iThome 鐵人賽

DAY 14
0
Modern Web

設計系統 - Design System系列 第 14

[Day 14] Design System - Token to CSS

  • 分享至 

  • xImage
  •  

本系列文章會在筆者的部落格繼續連載!Design System 101 感謝大家的閱讀!

前言

HiHi! 中秋愉快!

建立 Design Token

Image

在上面的篇章,我們提到了 style dictionary 的概念,以及如何運用它來管理視覺元素,而大家還記得先前提到從 figma 到 css 整個實踐的架構圖嗎?

沒錯!今天我們就要來實踐整個架構,而以下會是整個實踐的流程:

  1. 建立一個新的專案,而專案名稱為 design-tokens
  2. 了解視覺元素的結構,這裡會以 Material Design 當作基底
  3. 將視覺元素 (color, font 以及 shadow 等等) 轉換成 key-value pair 的 json 檔
  4. 最後在透過 style-dictionary 來產生不同平台的 Styling (本篇會以 Web 的 CSS 作為範例)

Design System Overview

本篇將加入 design-tokens 這個 package,而從系列的第一篇文章至今,整體的 Design System 結構會是這樣:

design-system
├── README.md
├── package.json
├── pnpm-lock.yaml
├── packages
│   ├── components
|   |  ├── focus-scope
|   |  |── visually-hidden
│   └── tsconfig
|   |── design-tokens <-- new
...

Step.1 - 初始化 design-tokens

建立 packages.json

首先在 packages 下新增一個 design-tokens 的資料夾,並且初始化 packages.json。

design-system > mkdir design-tokens
design-system > cd design-tokens
design-system > pnpm init

安裝相關套件

design-tokens 專案下安裝以下套件:

  • style-dictionary: 管理 Design Token 的套件
  • sass: 為 CSS 的預處理器,可以用更有組織性的方式來寫 CSS
  • stylelint: CSS 的 linter
pnpm add style-dictionary sass postcss stylelint stylelint-config-prettier stylelint-config-standard stylelint-config-standard-scss stylelint-order stylelint-prettier -D

設定 Stylelint

design-tokens 的根目錄底下建立 stylelintrc.json

design-system > touch stylelintrc.json

可以根據喜好設定 Stylelint,這是筆者的設定檔

Step.2 - 將視覺元素轉換成 Design Token

這次筆者會以 Material Design 的視覺元素與組件設計檔來作為 Design System 的基底。

Material Design 將 Design Token 切分成三個層級,分別為 Reference Token, System Token 以及最底層的 Component Token。

每一層的關係都在之前提過,可以參考 Design System 101 - Design Token,這裡就不在贅述。

Image

Step.3 - 管理 Design Token

由於 Material Design 將 Token 切分成三個層級,第一個問題就是要先定義哪一層級的 Token 需要納入 design-token 這個 packages 中管理?

在目前的架構中,筆者會將 Reference Token 與 System Token 納入 design-token,而 Component Token 則是放在各個組件中。

這也是現今許多 Design System 的做法,如 Pinterest 的 Gestalt 或是 Shopify 的 Polaris 等等。

視覺元素轉化成 JSON

接下來要將 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.jsonalias.json,而在 alias.json 內的值則會參照 base.json

這也呼應了前面所提到的一致性,當設計師或是當今天想要 rebrand,就只需要更改 Reference Token 的值,而不需要更改所有的 Design Token。

Reference Token - base.json

Image

在 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 - alias.json

Image

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

Step.4 透過 style-dictionary 來產生不同平台的 Styling

最後在透過 style-dictionary 來產生不同平台的 Styling,而其會需要一個 config.js 來定義所有建置邏輯。

style-dictionary 還有另一個優點就是可以透過一些客製化的 script 來對其進行擴充,先來介紹最基本的用法。

建立 config.js

{
  "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 等等,而每個平台都會有 transformGroupfiles,可以參考 style-dictionary 的文檔。

而以下是筆者的設定

  1. 透過 build.js 將 config.json 做延伸,並且定義對應的 transformGroupfiles
  2. 再來當 style-dictionary 將先前定義好的 token 轉換成 CSS 後,我們可以透過 SASS 建立 CSS 基底,並將所有 css 引入 normalized.scss 作為入口,在打包時建立出 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');

上一篇
[Day 13] Design System - Style Dictionary
下一篇
[Day 15] Design System - Layout
系列文
設計系統 - Design System30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言