Design System18 OCT, 20267 phút đọc

Quản lý variables trong design system: cấu trúc ba tầng cho sản phẩm có dark mode

Quản lý variables trong design system: cấu trúc ba tầng cho sản phẩm có dark mode

Mình từng mở một file design system và thấy cùng một màu xám được nhập tay ở hơn chục chỗ, mỗi chỗ lệch nhau vài mã hex. Đổi thương hiệu một lần là phải sửa từng layer. Variables trong Figma sinh ra để chấm dứt chuyện đó, nhưng chỉ khi bạn tổ chức chúng có chủ đích. Bài này là cách mình dựng và quản lý variables cho một design system của sản phẩm di động có dark mode, kèm những quy ước mình thấy đáng giữ.

Sơ đồ ba tầng variables: Primitives, Semantic tokens và Component, tham chiếu từ trên xuống dưới
Ba tầng, một chiều tham chiếu.

Bắt đầu từ cấu trúc file, không phải từ màu

Trước khi tạo biến nào, mình sắp xếp file. Các page nền tảng đứng đầu: Color, Typography, Spacing, Corner Radius, Shadows, Backdrop Blur, cộng thêm Anatomy và Design annotations. Sau đó mới đến Core Components, chia nhóm bằng những page phân cách để thanh Pages dễ quét.

Thứ tự này không chỉ để cho đẹp. Component phụ thuộc vào foundations, nên đặt foundations lên trước nhắc cả team rằng muốn sửa component thì nhìn lên trên xem token đã đủ chưa.

Cấu trúc page trong file design system: Foundations ở trên, Core Components ở dưới
Foundations trước, component sau.

Tầng 1: Primitives, màu thô và không mang ý nghĩa

Collection đầu tiên chỉ chứa giá trị thô. Mỗi hue có một thang từ 100 đến 900, trong đó 500 là màu gốc. Riêng Grey có thêm 0, 850 và 950 vì dark mode cần nhiều bậc tối hơn. Collection này chỉ có một mode, và có một quy tắc: designer không bao giờ gắn primitives trực tiếp vào component.

Tên kiểu color/Primary/500 cho biết nó là màu gì, nhưng không cho biết dùng vào đâu. Chuyện “dùng vào đâu” thuộc về tầng sau.

Bảng màu primitives gồm chín hue thang 100 đến 900 và thang Grey từ 0 đến 950
Primitives: 93 biến màu, một mode.

Tầng 2: Semantic tokens, đặt tên theo vai trò

Đây là tầng quan trọng nhất. Mỗi token mô tả một vai trò: bg-surface, text-secondary, icon-disabled, stroke-brand-primary. Collection này có hai mode là Light và Dark, và mỗi mode trỏ về một primitive khác nhau.

Vài điều mình thấy hay khi làm dark mode:

Nhờ vậy một button chỉ cần gắn Colors/Main/Primary/solid. Chuyển mode của layer từ Light sang Dark, mọi thứ tự đổi theo.

So sánh cùng một giao diện ở mode Light và Dark, kèm bảng token trỏ về primitives
Một token, hai mode. Bảng bên dưới là cách token trỏ về primitives.

Mỗi collection một việc

Mình tách variables thành nhiều collection thay vì gom hết vào một. Mỗi collection chứa đúng một loại giá trị: màu thô, màu theme, typography, spacing, stroke, radius, icon size, định dạng ngày giờ, định dạng dữ liệu và kiểu tiêu đề. Cách này có ba lợi ích: dễ tìm, dễ phân quyền sửa và dễ publish từng phần.

Ba quy ước nhỏ giúp bảng Variables gọn gàng:

Danh sách mười một collection variables với số lượng biến và mode của từng collection
11 collection, mỗi cái một việc.

Thang số cũng là variables

Không chỉ màu. Spacing, corner radius, stroke weight và icon size đều là biến kiểu Number. Spacing có 18 bước từ 0 đến 256, radius có 8 bước đến 999 cho hình tròn, stroke có 3 bước, icon size có 13 bước từ 10 đến 128.

Lợi ích lớn nhất là kỷ luật: designer chọn từ thang có sẵn thay vì gõ số lẻ như 13 hay 22. Muốn đổi cảm giác cả sản phẩm, chẳng hạn bo góc mềm hơn, bạn đổi giá trị của vài biến radius thay vì sửa từng layer.

Thang spacing, corner radius, stroke weight và icon size dưới dạng variables
Spacing, radius, stroke, icon size.

Typography: size và line-height đi thành cặp

Collection typography có 36 biến: hai biến font family (heading và body), bốn biến font weight, và mỗi vai trò chữ có một cặp font size và line-height. Text style trong Figma chỉ việc gắn vào các biến này. Khi cần chỉnh thang chữ, bạn sửa ở một nơi và mọi text style cập nhật theo.

Thang chữ từ H1 đến Caption với cặp font size và line-height
Thang chữ: mỗi vai trò một cặp size và line-height.

Dùng mode để đổi cả bộ kiểu chữ

Mình thích nhất collection “Title Type”. Nó có bốn mode (32, 24, 20, 16), mỗi mode trỏ tới một cỡ chữ tiêu đề, line-height, letter-spacing và cỡ chữ phụ tương ứng. Một component tiêu đề duy nhất, đổi mode là đổi cả bộ. Không cần tạo bốn biến thể và cũng không phải nhớ chỉnh letter-spacing bằng tay.

Một tiêu đề hiển thị ở bốn mode 32, 24, 20 và 16 với các biến kiểu chữ thay đổi theo
Một component, bốn mode.

Biến String cho dữ liệu hiển thị

Variables có bốn kiểu: Color, Number, String và Boolean. Mình tận dụng cả String. Một collection lưu chuỗi mẫu cho các định dạng dữ liệu như số điện thoại hoặc email, với ba mode: hiện đầy đủ và hai kiểu che. Một collection khác lưu định dạng ngày giờ theo hai locale. Mock-up nào cũng lấy dữ liệu mẫu từ đây, nên bản thiết kế và bản thật cùng một quy ước và không còn cảnh mỗi màn hình một kiểu ngày.

Biến String cho định dạng dữ liệu che và hiện, và định dạng ngày giờ theo hai locale
Giá trị trong ảnh là ví dụ minh họa.

Shadow và blur thì dùng style

Variables chưa lưu được hiệu ứng, nên bóng đổ và blur vẫn nằm ở Effect styles. Mình đặt tên chúng theo cùng một thang xs, sm, md, lg, xl để dễ nhớ như các thang còn lại. Bóng đổ trong hệ thống này rất nhẹ, độ đậm chỉ từ 3 đến 9 phần trăm.

Năm mức bóng đổ từ xs đến xl và các mức backdrop blur
Effect styles: shadows và backdrop blur.

Checklist quản lý variables

Sau khi dựng xong, phần khó là giữ cho nó không hỏng theo thời gian. Mình dùng danh sách này:

  1. Không gắn primitives vào component. Luôn đi qua semantic token.
  2. Đặt scope cho từng biến. Biến nền chỉ nên hiện khi chọn fill, biến spacing chỉ hiện ở gap và padding. Danh sách chọn ngắn lại thấy rõ.
  3. Đổi tên thay vì xóa. Figma gắn biến theo ID nên đổi tên không làm đứt liên kết, còn xóa biến đang dùng thì có.
  4. Kiểm tra cả hai mode mỗi khi thêm token. Token mới mà thiếu giá trị Dark là lỗi dễ lọt nhất.
  5. Quét màu gắn tay. Chọn cả frame, mở Selection colors, thấy màu nào chưa gắn biến thì thay bằng token.
  6. Ghi lại thay đổi. Mỗi lần publish library, viết vài dòng ghi chú để team biết vừa đổi gì.
  7. Giữ chuỗi tham chiếu ngắn. Primitive, semantic, rồi dừng. Càng nhiều tầng trung gian càng khó truy ngược.

Kết

Variables không làm design system tốt lên một mình. Cái tạo ra khác biệt là quy ước: tầng nào chứa gì, đặt tên ra sao và ai được sửa. Nếu bạn đang bắt đầu, hãy làm ba việc trước: tách primitives khỏi semantic, đặt tên theo vai trò, và dựng Light và Dark ngay từ đầu. Phần còn lại có thể thêm dần.

Nếu bạn đang dựng design system và muốn trao đổi, cứ nhắn mình qua mục liên hệ nhe!

← Quay lại Blog Bài tiếp theo10 nguyên tắc usability của Nielsen: kim chỉ nam cho mọi giao diện →