Menu
ESC

Nhập từ khóa để tìm kiếm

↑↓ Di chuyển
Enter Mở
ESC Đóng

Đang tải...

Bài 12 — Components & Variants

UI Design and Design Handoff Bài 12/60

Mở đầu — vì sao bài này quan trọng

Hãy tưởng tượng bạn vừa thiết kế xong một màn hình cho app ngân hàng số. Trong đó có 40 cái nút bấm rải rác khắp các màn hình: nút "Chuyển tiền", nút "Thanh toán", nút "Đăng nhập"... Một sáng thứ Hai, trưởng nhóm thiết kế nhắn: "Sếp muốn đổi màu nút chính từ xanh dương sang xanh lá, và bo góc từ 4px thành 8px". Nếu 40 cái nút đó là 40 hình chữ nhật độc lập, bạn sẽ mất cả buổi sáng đi sửa từng cái, và gần như chắc chắn bỏ sót vài cái nằm ở màn hình ít ai để ý.

Đây chính là bài toán mà Components (thành phần) và Variants (biến thể) sinh ra để giải quyết. Nếu Auto Layout ở bài trước là bộ xương giúp giao diện co giãn thông minh, thì Components là hệ thống "nhân bản có kiểm soát" — cho phép bạn định nghĩa một thứ đúng một lần, rồi tái sử dụng ở khắp nơi mà mọi bản sao vẫn đồng bộ với nhau. Đây là ranh giới rõ rệt phân biệt một designer nghiệp dư (kéo thả từng phần tử) với một designer làm việc theo hệ thống (thiết kế có cấu trúc, có thể mở rộng).

Với những ai hướng tới việc xây dựng Design System — thứ mà toàn bộ nửa sau khóa học này xoay quanh — thì Components chính là viên gạch nền móng. Không nắm vững nó, bạn không thể làm việc nghiêm túc với Figma hiện đại.

Khái niệm cốt lõi

Main Component và Instance

Trong Figma, khi bạn biến một nhóm phần tử thành component, Figma tạo ra hai loại đối tượng:

  • Main component (component gốc) — đây là "nguồn thật" (source of truth). Nó giống như bản thiết kế gốc, khuôn đúc chính thức. Trong Figma, main component thường có biểu tượng hình kim cương màu tím và nằm ở một trang riêng biệt (thường đặt tên là "🧩 Components" hoặc "Assets").
  • Instance (bản thể) — là bản sao được "liên kết ngược" (linked) với main component. Khi bạn kéo một component từ panel Assets vào canvas, thứ bạn đặt xuống là một instance, không phải bản gốc. Instance có biểu tượng hình kim cương rỗng.
Nguyên tắc vàng cần khắc cốt ghi tâm: Sửa main → mọi instance tự động cập nhật theo. Bạn đổi màu nút ở main component, ngay lập tức cả 40 instance trên khắp file đều đổi màu. Đây chính là lời giải cho bài toán ở đầu bài.

Nhưng chiều ngược lại thì không đúng hoàn toàn. Từ một instance, bạn có thể override (ghi đè) một số thuộc tính riêng — như đổi chữ bên trong, đổi màu, ẩn/hiện một phần tử con — mà không ảnh hưởng đến main. Ví dụ: main component là một nút với chữ mặc định "Button", nhưng ở instance thứ nhất bạn ghi đè thành "Chuyển tiền", instance thứ hai thành "Thanh toán". Cả hai vẫn giữ liên kết với main, nên nếu main đổi màu thì chúng đổi màu theo, nhưng phần chữ đã override vẫn được giữ nguyên.

Cơ chế override này là điểm tinh tế nhất và cũng dễ gây bối rối nhất. Hãy nhớ: override sống ở tầng instance, còn cấu trúc và style mặc định sống ở tầng main.

Vì sao không dùng Copy-Paste thường?

Nhiều người mới hỏi: "Sao không cứ Ctrl+C, Ctrl+V một cái nút đẹp rồi dán khắp nơi?" Câu trả lời: bản dán thường (duplicate) là những đối tượng độc lập, không liên kết. Sửa cái này không ảnh hưởng cái kia. Với 3-4 phần tử thì không sao, nhưng với một sản phẩm thật có hàng trăm màn hình, đây là công thức dẫn tới sự hỗn loạn (inconsistency) — mỗi nơi một kiểu, không ai đồng bộ nổi.

Variants — biến thể của cùng một component

Một nút thật ngoài đời không chỉ có một trạng thái. Nó có:

  • Trạng thái: Default, Hover, Pressed, Disabled.
  • Kiểu: Primary, Secondary, Ghost.
  • Kích thước: Small, Medium, Large.
  • Có/không có icon.
Nếu mỗi tổ hợp là một component riêng, bạn sẽ có hàng chục component rời rạc trong panel Assets, tên dài dằng dặc, tìm mỏi mắt. Variants giải quyết điều này: nó gom nhiều component có liên quan vào chung một component set (bộ thành phần), rồi phân loại chúng bằng các properties (thuộc tính).

Ví dụ, thay vì có Button/Primary/Large/Hover, Button/Primary/Large/Default... nằm rời rạc, bạn có một component set duy nhất tên Button với các properties: Type (Primary/Secondary/Ghost), Size (S/M/L), State (Default/Hover/Disabled). Khi kéo instance vào canvas, người dùng chỉ cần chọn giá trị từ các menu thả xuống ở panel bên phải — cực kỳ trực quan, giống như chọn cấu hình khi mua điện thoại.

Các loại Component Properties

Figma hiện đại cung cấp bốn loại thuộc tính, bạn nên phân biệt rõ:

  • Variant — chọn từ danh sách cố định (như State: Default/Hover). Mỗi variant là một biến thể hình ảnh riêng.
  • Boolean — bật/tắt một phần tử (ví dụ: "Show Icon" true/false).
  • Text — cho phép thay đổi nội dung chữ ngay từ panel, không cần vào sâu.
  • Instance swap — cho phép hoán đổi một component con bên trong (ví dụ: đổi icon từ mũi tên sang dấu cộng).
Ta sẽ đào sâu tư duy thiết kế các property này ở Bài 13; trong bài này bạn chỉ cần nắm rằng chúng tồn tại và biết tạo Variant cơ bản.

Tình huống thực tế

Ví dụ 1 — Startup fintech ở TP.HCM và bài toán 40 cái nút

Một startup fintech tại Quận 1, TP.HCM, đội thiết kế 3 người, đang xây app cho vay tiêu dùng. Ban đầu, do gấp deadline gọi vốn, họ copy-paste nút bấm khắp 60 màn hình prototype. Đến vòng gọi vốn Series A, nhà đầu tư yêu cầu rebrand: đổi màu thương hiệu từ cam sang tím, đổi font, bo góc mềm hơn.

Bạn Linh, designer chính, kể lại: nhóm mất gần 3 ngày công chỉ để dò tìm và sửa tay từng nút, và khi demo vẫn còn 5-6 nút màu cam lọt lưới, khiến buổi demo mất điểm. Sau vụ đó, họ dừng lại một tuần để refactor toàn bộ sang component. Kết quả: lần rebrand tiếp theo (khi ra mắt thị trường), việc đổi toàn bộ hệ thống nút chỉ mất đúng 20 phút — sửa 1 main component, mọi instance tự cập nhật.

Bài học: Chi phí bỏ qua component không mất ngay, nó "nợ" lại và tính lãi vào lúc bạn cần thay đổi. Component là khoản đầu tư trả trước để mua sự linh hoạt về sau.

Ví dụ 2 — Nhóm outsource và sự cố "instance bị detach"

Một công ty outsource ở Đà Nẵng làm dự án cho khách Nhật. Junior designer, trong lúc muốn "sửa cho nhanh" một nút bị lệch, đã bấm Detach Instance (tách bản thể khỏi main). Nút đó trở thành nhóm hình độc lập, đứt liên kết. Vài tuần sau khách yêu cầu đổi hệ thống màu, cả team update main component — nhưng riêng màn hình có nút bị detach thì không đổi theo, gây ra một nút lạc màu trên bản giao cho khách.

Điều tệ là detach không để lại dấu vết rõ ràng — nhìn bề ngoài nút vẫn y hệt. Chỉ khi soi kỹ mới thấy nó không còn biểu tượng kim cương. Team sau đó ra quy ước: cấm detach trừ khi có lý do đặc biệt và phải ghi chú lại, đồng thời dùng plugin để quét các instance bị tách.

Bài học: Detach là con dao hai lưỡi. Nó hữu ích khi bạn cần một phiên bản thực sự khác biệt vĩnh viễn, nhưng lạm dụng nó sẽ phá vỡ toàn bộ lợi ích của hệ thống component.

Ví dụ 3 — Grab và tư duy variant cho nút đa trạng thái

Hãy nhìn một sản phẩm quy mô lớn như Grab (giả định dựa trên cách các design system lớn vận hành). Một nút "Đặt xe" không đơn giản: nó có trạng thái bình thường, trạng thái đang loading (khi hệ thống tìm tài xế), trạng thái disabled (khi chưa chọn điểm đến), và biến thể trên nền sáng/tối. Nếu mỗi trạng thái là một component rời, designer sẽ phải nhớ tên và kéo thả đúng — dễ nhầm.

Với variants, họ định nghĩa một component set Button với property State. Khi làm prototype luồng đặt xe, designer chỉ việc chọn một instance rồi đổi State từ "Default" sang "Loading" ở dropdown — không cần đi tìm component khác. Điều này giúp việc dựng prototype (Bài 32) nhanh và nhất quán hơn hẳn.

Bài học: Variant không chỉ để gọn gàng, nó phản ánh đúng cách một phần tử UI thực sự "sống" qua nhiều trạng thái. Gom các trạng thái liên quan lại giúp cả team tư duy về UI như một đối tượng có hành vi, không phải hình vẽ tĩnh.

Hướng dẫn từng bước

Phần A — Tạo Main Component đầu tiên

  • Dựng phần tử nguồn. Thiết kế một nút bấm hoàn chỉnh: dùng Auto Layout (đã học ở Bài 11) cho một frame chứa text "Button", padding ngang 16px, dọc 12px, nền màu, bo góc 8px. Việc dùng Auto Layout ở đây rất quan trọng để nút tự co giãn theo độ dài chữ.
  • Chọn frame nút. Click chọn toàn bộ frame.
  • Create Component. Bấm tổ hợp phím Cmd/Ctrl + Option/Alt + K, hoặc bấm nút hình kim cương trên thanh công cụ. Viền frame chuyển sang màu tím — bạn vừa tạo main component.
  • Đưa main vào nơi ngăn nắp. Tạo một page riêng tên "Components", chuyển main component vào đó. Nguyên tắc: main component không nên nằm lẫn trong các màn hình thiết kế thật.
  • Dùng instance. Mở panel Assets (biểu tượng cuốn sách bên trái), tìm component Button, kéo vào màn hình. Thứ bạn vừa đặt là một instance.

Phần B — Tạo Variants

  • Chọn main component vừa tạo.
  • Ở panel bên phải, trong khu vực Properties, bấm dấu "+" cạnh mục Variant (hoặc bấm nút "Add variant" hiện ra dưới component). Figma sẽ nhân bản component thành một component set, bao quanh bằng khung nét đứt màu tím.
  • Đặt tên property. Figma tự tạo property tên Property 1 với giá trị Default. Đổi tên property thành State cho rõ nghĩa.
  • Chỉnh biến thể mới. Bản variant thứ hai, đổi giá trị thành Hover, rồi chỉnh màu nền đậm hơn một chút để thể hiện trạng thái hover.
  • Thêm variant nữa cho Disabled (giảm opacity xuống ~40%), Pressed, v.v. Mỗi lần thêm, chỉ cần đổi giá trị của property và tinh chỉnh hình ảnh.
  • Thêm property thứ hai nếu cần. Ví dụ property Size với S/M/L. Figma sẽ nhân tổ hợp — bạn có ma trận Size × State. Lưu ý: đừng để ma trận phình quá to (xem phần lỗi thường gặp).

Phần C — Sử dụng Variant khi làm việc

  • Kéo một instance của Button vào canvas.
  • Chọn instance, nhìn panel bên phải — bạn sẽ thấy các dropdown tương ứng với property (State, Size).
  • Đổi giá trị dropdown để chuyển trạng thái, không cần tìm component khác.
  • Ghi đè text: double-click vào chữ trên instance, gõ nội dung mới (ví dụ "Chuyển tiền"). Đây là override text, main vẫn giữ "Button".

Lỗi thường gặp & mẹo

Lỗi 1 — Đặt tên lộn xộn. Component tên Frame 27, Button copy 3 là ác mộng. Hãy đặt tên có cấu trúc phân cấp bằng dấu gạch chéo, ví dụ Button với properties rõ ràng, hoặc gom nhóm Icon/Arrow, Icon/Close. Tên tốt giúp panel Assets tự động tổ chức theo thư mục. (Chủ đề naming sẽ đào sâu ở Bài 34.)

Lỗi 2 — Bùng nổ tổ hợp variant (variant explosion). Nếu bạn có 4 Type × 3 Size × 5 State × 2 (có icon/không) = 120 variant trong một set, file sẽ nặng nề và khó bảo trì. Mẹo: những thứ nên là Boolean hoặc Instance-swap (như "có icon không") thì đừng biến thành variant. Chỉ dùng variant cho những khác biệt thực sự về hình ảnh trạng thái.

Lỗi 3 — Lạm dụng Detach. Như ví dụ Đà Nẵng ở trên. Trước khi detach, hãy tự hỏi: "Mình có thể đạt được điều này bằng override không?" Đa số trường hợp câu trả lời là có. Chỉ detach khi bạn thực sự cần một đối tượng vĩnh viễn tách khỏi hệ thống.

Lỗi 4 — Sửa nhầm main khi tưởng đang sửa instance. Luôn nhìn màu viền (tím = main/set) và biểu tượng kim cương (đặc = main, rỗng = instance) để biết mình đang ở đâu.

Mẹo hay:

  • Muốn tìm main từ một instance: chuột phải instance → Go to main component.
  • Muốn khôi phục instance về mặc định sau khi override lỡ tay: chuột phải → Reset all changes.
  • Dùng Auto Layout bên trong component để nút, thẻ, ô nhập tự co giãn — component không co giãn được sẽ vỡ layout khi nội dung dài ngắn khác nhau.
  • Publish component thành library (thư viện) khi làm việc nhóm để mọi người dùng chung một nguồn thật (sẽ nói kỹ hơn ở các bài về Design System).

Bài tập thực hành

  • Tạo một Button component hoàn chỉnh dùng Auto Layout, có padding, bo góc, màu nền.
  • Biến nó thành component set với 4 variant State: Default, Hover, Pressed, Disabled. Tự chọn cách thể hiện thị giác cho từng trạng thái (màu, opacity).
  • Thêm property Type với 2 giá trị: Primary (nền đặc) và Secondary (viền, nền trong suốt). Kiểm tra xem ma trận Type × State sinh ra bao nhiêu variant.
  • Kéo 5 instance ra một màn hình giả lập, mỗi instance override text khác nhau (Đăng nhập, Hủy, Xác nhận, Tiếp tục, Quay lại) và đặt ở trạng thái khác nhau.
  • Bài kiểm tra sức mạnh: quay lại main component, đổi bo góc từ 8px sang 16px. Quan sát cả 5 instance có tự cập nhật không. Nếu có — bạn đã hiểu đúng bản chất.
  • Thử nghiệm ranh giới: detach một instance, rồi lặp lại bước 5. Quan sát instance bị detach KHÔNG đổi theo, để tự mình cảm nhận vì sao detach nguy hiểm.

Tóm tắt

  • Main component là nguồn thật; instance là bản sao liên kết ngược với main. Sửa main → mọi instance cập nhật.
  • Override cho phép tùy biến instance (text, màu, ẩn/hiện) mà không phá liên kết với main; nhưng override sống ở tầng instance.
  • Variants gom nhiều biến thể liên quan vào một component set, phân loại bằng properties (Variant, Boolean, Text, Instance swap), giúp gọn gàng và phản ánh đúng các trạng thái thực của UI.
  • Tránh bốn cái bẫy: đặt tên lộn xộn, bùng nổ variant, lạm dụng detach, và sửa nhầm main/instance.
  • Component là nền móng của Design System — thứ giúp bạn thiết kế một lần, tái sử dụng và cập nhật ở quy mô lớn mà vẫn nhất quán. Nắm chắc bài này, bạn đã sẵn sàng để bước sang tư duy thiết kế "API" cho component ở Bài 13.