Giao diện hiếm khi chỉ có một hình dạng “bình thường”. Sau mỗi lần người dùng bấm, nhập, gửi, mất mạng, đổi quyền hoặc nhận dữ liệu mới, hệ thống chuyển sang một trạng thái khác. Nếu thiết kế chỉ mô tả ảnh tĩnh mà không quy định các chuyển đổi này, developer phải tự suy đoán và người dùng phải tự đoán hệ thống đang làm gì.

State-Based Design trong UI là gì? Từ snapshot đến transition
State-Based Design là cách thiết kế giao diện dựa trên tập trạng thái hợp lệ của hệ thống và quy tắc chuyển đổi giữa chúng. Một state là “snapshot” tại một thời điểm: dữ liệu nào đang có, hành động nào được phép, component phải hiển thị gì và công nghệ hỗ trợ cần nhận được thông tin nào.
| Khái niệm | Câu hỏi thiết kế | Ví dụ |
|---|---|---|
| State | Hệ thống đang ở tình trạng hợp lệ nào? | idle, submitting, success, error. |
| Event | Điều gì vừa xảy ra? | SUBMIT, RESOLVE, REJECT, RETRY. |
| Transition | Event đưa hệ thống từ state nào sang state nào? | submitting → success khi backend xác nhận. |
| Guard | Điều kiện nào phải đúng trước khi chuyển? | Chỉ gửi khi dữ liệu hợp lệ và chưa có request đang chạy. |
| Action/effect | Hệ thống thực hiện việc gì khi chuyển? | Gửi request, lưu draft, công bố status message. |
| Context/data | Dữ liệu nào tồn tại xuyên suốt state? | Giá trị form, error code, retry count và permission. |
Ví dụ, form không chỉ có “bình thường” và “lỗi”. Nó có thể ở editing, invalid, submitting, success, serverError, offline hoặc sessionExpired. Một số state loại trừ nhau; một số trạng thái tồn tại song song, chẳng hạn form vừa dirty vừa offline.
Mô hình state giúp loại bỏ impossible state. Nút không nên vừa “đã gửi thành công” vừa hiển thị spinner; modal không nên vừa đóng vừa giữ focus trap; dữ liệu không nên vừa “empty” vừa có 12 kết quả. Guard và transition rõ ràng giúp designer, developer và QA thống nhất logic thay vì sửa từng biểu hiện rời rạc.
Trạng thái nhìn thấy phải khớp trạng thái thật của hệ thống. Không được hiển thị “Đã gửi” chỉ vì người dùng bấm nút; success chỉ xuất hiện khi backend xác nhận outcome. Đây là ranh giới giữa feedback trang trí và phản hồi đáng tin.
Hệ sinh thái UI state: interaction, data, workflow và environment
Danh sách default, hover, active và focus chỉ bao phủ trạng thái trình bày của một control. Sản phẩm thực tế còn có trạng thái dữ liệu, bất đồng bộ, quyền, kết nối và toàn bộ workflow. State inventory nên được lập theo nhiều lớp để tránh chỉ thiết kế “happy path”.

Interaction state
Default, hover, focus-visible, pressed, selected, expanded và disabled. Phải hỗ trợ đúng phương thức nhập; hover không được là tín hiệu duy nhất.
Validation state
Untouched, editing, valid, invalid và validating. Lỗi phải được xác định bằng văn bản và có hướng sửa khi có thể.
Async state
Idle, pending, refreshing, resolved, rejected, timeout và retrying. Phân biệt tải lần đầu với làm mới dữ liệu đã có.
Data state
Empty, partial, populated, stale và conflicting. “Không có dữ liệu” phải khác “không tải được dữ liệu”.
Permission state
Anonymous, authenticated, authorized, read-only, denied và expired. UI không được hứa hành động mà backend sẽ từ chối.
Environment state
Online, offline, reconnecting, backgrounded, reduced-motion và low-capability. Cần fallback và giữ tiến độ khi phù hợp.
Workflow state
Draft, review, approved, published, archived hoặc cancelled. Mỗi state có quyền, hành động và audit trail riêng.
Completion state
Success, partial success, duplicate, queued hoặc failed. Thông báo phải khớp outcome thật và nêu bước tiếp theo.
State nên được đặt tên theo ý nghĩa nghiệp vụ, không chỉ theo màu hoặc component. paymentDeclined cung cấp nhiều thông tin hơn red; awaitingApproval rõ hơn disabled. Tên state tốt giúp code, analytics, tài liệu và hỗ trợ khách hàng dùng chung một ngôn ngữ.
Không phải mọi tổ hợp đều cần một màn hình riêng. Hãy tách state có ý nghĩa hành vi khỏi style variant. Kích thước nút hoặc màu thương hiệu là variant; pending, denied và success là state vì chúng thay đổi hành động, phản hồi hoặc dữ liệu.
Với các thành phần chuyển đổi như nút liên hệ, form báo giá, giỏ hàng hoặc UX của checkout page, thiếu một trạng thái nhỏ cũng có thể làm người dùng dừng lại ở bước quan trọng nhất.
Active, Focus và Hover khác nhau như thế nào?
Ba trạng thái này rất dễ bị gộp chung, nhưng trong UI thực tế chúng phục vụ ba loại tín hiệu khác nhau.
- Hover trả lời câu hỏi: “Thành phần này có thể tương tác không?” Nó xảy ra khi con trỏ chuột đi qua component.
- Active trả lời câu hỏi: “Hành động bấm đã được ghi nhận chưa?” Nó thường xuất hiện trong khoảnh khắc người dùng nhấn chuột, chạm màn hình hoặc kích hoạt control.
- Focus trả lời câu hỏi: “Tôi đang ở đâu trong giao diện?” Nó đặc biệt quan trọng với người dùng bàn phím, screen reader hoặc các luồng nhập liệu dài.
W3C/WAI giải thích rằng mục đích của tiêu chí Focus Visible là giúp người dùng biết phần tử nào đang có keyboard focus. Vì vậy, focus ring không nên bị xóa chỉ vì “nhìn không đẹp”. Nếu cần tùy biến, hãy thiết kế focus state rõ ràng, có độ tương phản tốt và nhất quán với design system. Xem hướng dẫn Focus Visible của W3C/WAI.
Một lỗi thường gặp trong website doanh nghiệp là CTA có hover đẹp trên desktop nhưng không có focus state. Điều này khiến trải nghiệm bàn phím bị gãy, đặc biệt ở form liên hệ, menu, tab nội dung hoặc bước thanh toán. Nếu bài viết hoặc landing page đang nhấn mạnh CTA, bạn cũng nên kiểm tra thêm phần thiết kế button call to action để bảo đảm nút vừa nổi bật vừa dễ sử dụng.
State-Map Framework: từ component đến state transition table
Một state map có thể bắt đầu bằng chuỗi Component → Event → Guard → Transition → Feedback → Recovery. Với workflow phức tạp, thêm context/data, action/effect, analytics và owner. Mục tiêu là mô tả hệ thống đủ rõ để triển khai và kiểm thử, không phải tạo sơ đồ trang trí.

Các trường trong State-Map Framework
- Current state: snapshot hợp lệ trước khi event xảy ra.
- Event: hành động người dùng, phản hồi server, timeout, permission change hoặc system event.
- Guard: điều kiện cho phép hoặc từ chối transition.
- Next state: snapshot hợp lệ sau transition.
- Action/effect: request, lưu dữ liệu, log hoặc chuyển focus cần thực hiện.
- Visual feedback: label, spinner, inline message, progress hoặc thay đổi control.
- Accessibility behavior: name/role/state/value, focus destination và status announcement.
- Recovery: retry, undo, sửa dữ liệu, đăng nhập lại hoặc hỗ trợ.
- Telemetry: event nào xác nhận exposure, error, success và abandonment.
Ví dụ state transition table cho form tư vấn:
| Current state | Event | Guard | Next state | Feedback/recovery |
|---|---|---|---|---|
| editing | SUBMIT | Dữ liệu hợp lệ và chưa gửi | submitting | Nút “Đang gửi…”, khóa submit trùng, giữ dữ liệu. |
| editing | SUBMIT | Dữ liệu không hợp lệ | invalid | Lỗi bằng chữ gần trường; focus tới lỗi đầu tiên phù hợp. |
| submitting | RESOLVE | Backend xác nhận | success | Công bố status, mã tham chiếu và bước tiếp theo. |
| submitting | REJECT | Lỗi có thể thử lại | serverError | Giữ dữ liệu, nêu lỗi và nút thử lại. |
| submitting | OFFLINE | Không có kết nối | offline | Thông báo chưa gửi; retry khi kết nối trở lại. |
| serverError | RETRY | Còn phiên và có mạng | submitting | Gửi lại idempotent, không tạo bản ghi trùng. |
WAI-ARIA yêu cầu component tùy chỉnh cung cấp đúng name, role, state và value để công nghệ hỗ trợ hiểu được. Status message quan trọng như “Đã thêm vào giỏ” hoặc “Có 4 kết quả” cũng cần được xác định bằng markup phù hợp mà không buộc chuyển focus không cần thiết.
State map nên được version cùng requirement. Khi business rule đổi—ví dụ thêm phê duyệt, retry limit hoặc quyền read-only—sơ đồ, component, analytics và test case phải được cập nhật cùng nhau.
Tư duy component-based: quản trị trạng thái trong Design System
Điểm mù lớn của nhiều designer mới là thiết kế theo “màn hình”. Họ vẽ trang chủ, trang dịch vụ, trang liên hệ, nhưng mỗi lần cần nút hoặc input lại copy một phiên bản mới. Cách làm này tạo ra file thiết kế phình to, khó bảo trì và dễ lệch giao diện khi dự án lớn dần.
State-Based Design cần đi cùng tư duy component-based. Thay vì vẽ 20 button rời rạc, hãy tạo một button component có các variants rõ ràng:
type=primary / secondary / ghoststate=default / hover / active / focus / disabled / loadingsize=small / medium / largeicon=none / left / right
Figma khuyến nghị dùng variants để tùy chỉnh properties và values, giúp design system gần hơn với cách front-end triển khai component. Xem tài liệu Figma về variants. Với đội làm website, điều này giúp giảm tình trạng “mỗi trang một kiểu nút”, đồng thời làm cho hand-off rõ hơn.
Nếu đang xây dựng lại website hoặc landing page, bạn có thể kết hợp State-Based Design với công cụ phát triển UX/UI và một bộ component library nhỏ. Không nhất thiết phải xây design system lớn như sản phẩm SaaS; chỉ cần chuẩn hóa các thành phần lặp lại như header, menu, CTA, form, card dịch vụ, testimonial, bảng giá và modal.
Loading, Empty và Error: thiết kế trạng thái bất đồng bộ đáng tin
Loading, empty và error không phải ba màn hình độc lập đơn giản. Chúng cần phản ánh đúng nguyên nhân và dữ liệu hiện có. “Chưa có dữ liệu”, “không tìm thấy kết quả”, “không có quyền”, “mất mạng” và “server lỗi” đòi hỏi thông điệp cùng hành động khác nhau.

Loading: phân biệt initial load, refresh và progress
Khi chưa có dữ liệu, skeleton hoặc progress có thể giữ cấu trúc và báo hệ thống đang làm việc. Khi làm mới dữ liệu đã có, không nên xóa toàn bộ nội dung rồi thay bằng spinner nếu người dùng vẫn có thể đọc bản cũ. Với tác vụ có tiến độ đo được, progress indicator phù hợp hơn spinner vô hạn.
- Phản hồi ngay sau action để tránh submit lặp.
- Không làm biến mất dữ liệu người dùng đang cần nếu chỉ refresh nền.
- Có timeout, cancel hoặc retry cho tác vụ dài khi phù hợp.
- Tôn trọng reduced motion và tránh animation gây khó chịu.
Empty: xác định vì sao trống
| Loại empty | Thông điệp | Hành động |
|---|---|---|
| First use | Chưa có dữ liệu vì người dùng mới. | Tạo mục đầu tiên hoặc xem ví dụ. |
| No result | Bộ lọc/tìm kiếm không có kết quả. | Xóa bộ lọc, sửa query hoặc xem tất cả. |
| Completed | Không còn việc cần xử lý. | Xác nhận hoàn tất hoặc chuyển bước tiếp theo. |
| Permission | Dữ liệu tồn tại nhưng người dùng không được xem. | Yêu cầu quyền hoặc liên hệ owner. |
| Error masquerading as empty | Không tải được dữ liệu. | Thông báo lỗi và retry; không nói “không có dữ liệu”. |
Đây là điểm nối tự nhiên với user onboarding: trạng thái trống đầu tiên thường là lúc người dùng cần hướng dẫn rõ nhất.
Error: xác định lỗi, hậu quả và đường phục hồi
WCAG yêu cầu lỗi nhập liệu được xác định bằng chữ; khi có thể, hệ thống nên gợi ý cách sửa. Error message phải nằm gần nguồn lỗi hoặc được liên kết chương trình với trường tương ứng. Không chỉ đổi viền sang đỏ, vì màu không đủ cho mọi người dùng.
- Kém: “Invalid input.”
- Tốt hơn: “Email chưa đúng định dạng. Ví dụ: ten@domain.com.”
- Kém: “Submit failed.”
- Tốt hơn: “Chưa gửi được yêu cầu do mất kết nối. Dữ liệu vẫn được giữ; hãy thử lại khi có mạng.”
Error state nên giữ dữ liệu hợp lệ, phân biệt lỗi người dùng với lỗi hệ thống, tránh đổ lỗi và cung cấp mã tham chiếu khi support cần truy vết. Success state cũng phải nêu kết quả, thời gian tiếp theo và cách sửa/hoàn tác nếu hành động có thể đảo ngược.
Khi Error State trở thành cơ hội tăng chuyển đổi
Nhiều đội xem lỗi là phần kỹ thuật. Nhưng với CRO, error state là thời điểm người dùng đang ở rất gần hành động chuyển đổi nhưng bị chặn lại. Nếu phản hồi mơ hồ, họ rời đi. Nếu phản hồi rõ và hướng dẫn được cách sửa, họ tiếp tục.
Một error state có khả năng giữ chuyển đổi thường có bốn yếu tố:
- Đúng vị trí: lỗi nằm ngay cạnh trường hoặc khu vực gây lỗi, không chỉ hiện toast ở góc màn hình.
- Ngôn ngữ dễ hiểu: tránh mã lỗi hoặc câu kỹ thuật nếu người dùng không cần biết.
- Hướng xử lý cụ thể: nói người dùng cần sửa gì, thử lại ở đâu, hoặc liên hệ ai.
- Giữ dữ liệu đã nhập: không bắt người dùng nhập lại từ đầu sau một lỗi nhỏ.
Ví dụ trong form báo giá thiết kế website, nếu người dùng nhập thiếu số điện thoại, thông báo “Vui lòng nhập số điện thoại 10 chữ số để WebsiteHCM liên hệ lại” tốt hơn nhiều so với “Form invalid”. Với landing page, từng dòng microcopy trong error state có thể quyết định người dùng có hoàn tất form hay không.
Stress Test: kiểm thử transition, concurrency và recovery
Stress test state không chỉ thử dữ liệu dài. Hãy cố tình tạo event sai thứ tự, request trùng, phản hồi chậm, session hết hạn, permission đổi và nhiều trạng thái cùng lúc. Mục tiêu là tìm impossible state, race condition, dữ liệu mất và đường phục hồi bị đứt trước khi hand-off.

Checklist Stress Test cho UI States
- Dữ liệu cực trị: rỗng, một mục, hàng nghìn mục, chuỗi dài, ký tự đặc biệt, giá trị âm hoặc vượt giới hạn.
- Event lặp: double-click, submit nhiều lần, Back/Forward, refresh và retry liên tục.
- Out-of-order response: request cũ trả sau request mới; UI không được ghi đè dữ liệu mới bằng dữ liệu cũ.
- Network: offline, chập chờn, timeout, reconnect và background/foreground.
- Permission/session: quyền đổi giữa tác vụ, token hết hạn, account bị khóa hoặc dữ liệu read-only.
- Concurrency: cùng dữ liệu được sửa ở tab hoặc thiết bị khác.
- Accessibility: focus order, focus restoration, status announcement, keyboard và reduced motion.
- Recovery: giữ draft, undo, retry idempotent, hỗ trợ và rollback.
| Test case | Expected state | Evidence |
|---|---|---|
| Bấm submit hai lần | Một request hợp lệ; nút ở submitting; không tạo record trùng. | Network log và backend ID. |
| Request B hoàn tất trước A | Kết quả B vẫn là dữ liệu hiện hành. | State log và UI snapshot. |
| Mất mạng khi đang nhập | Draft được giữ; trạng thái offline rõ; retry được. | Storage/backend và task test. |
| Session hết hạn khi gửi | Không mất dữ liệu; đăng nhập lại rồi tiếp tục hoặc lưu nháp. | Authentication flow. |
| Modal đóng bằng Escape | Đóng modal và trả focus về control mở. | Keyboard/focus test. |
| Status thay đổi không nhận focus | Thông báo được công nghệ hỗ trợ công bố phù hợp. | Screen-reader test. |
Coverage nên theo transition, không chỉ theo screenshot. Ghi state trước, event, state sau, expected feedback, backend outcome và analytics event. Một flow có 10 màn hình nhưng 40 transition; kiểm thử 10 ảnh không chứng minh 40 đường chuyển hoạt động.
Cách kiểm tra này đặc biệt quan trọng với website có form dài, trang tài khoản, checkout, bộ lọc sản phẩm hoặc dashboard. Một website có thể đẹp trong ảnh chụp, nhưng nếu vỡ ở các trạng thái vận hành, người dùng vẫn đánh giá là thiếu chuyên nghiệp. Đây cũng là lý do nhiều dự án “đẹp nhưng không hiệu quả” cần audit lại từ luồng trạng thái, không chỉ từ giao diện trang chủ. Bạn có thể xem thêm bài website đẹp nhưng không hiệu quả để soi lại vấn đề ở góc chuyển đổi.
Checklist nghiệm thu UI cho Designer và Developer trước khi hand-off
Trước khi bàn giao file UI, hãy kiểm tra theo checklist dưới đây. Mục tiêu không phải làm file thiết kế phức tạp hơn, mà là giúp developer hiểu chính xác sản phẩm cần phản hồi thế nào trong từng tình huống.
- Component quan trọng đã có default, hover, active, focus, disabled và loading state.
- Input đã có empty, typing, valid, invalid, helper text và error message.
- CTA chính có trạng thái đang gửi và không cho submit lặp.
- Error message nói rõ vấn đề, nằm đúng vị trí và có hướng sửa.
- Empty state có lời hướng dẫn, không chỉ là “không có dữ liệu”.
- Focus state đủ rõ cho người dùng bàn phím.
- Trạng thái loading không làm người dùng mất dữ liệu đã nhập.
- Mobile state đã được kiểm tra với bàn phím ảo, tap target và chiều rộng nhỏ.
- Design token hoặc variant naming đủ rõ để developer triển khai.
- File hand-off có ghi chú trạng thái đặc biệt, không để developer tự đoán.
Với dự án website, checklist này nên được đưa vào quy trình nghiệm thu cùng checklist bàn giao website. Nếu thiếu phần trạng thái, đội kỹ thuật vẫn có thể hoàn thành chức năng, nhưng trải nghiệm cuối cùng sẽ phụ thuộc vào suy đoán của từng developer.
Áp dụng State-Based Design vào website doanh nghiệp
Với website doanh nghiệp, State-Based Design không nhất thiết phải bao phủ hàng trăm component như một sản phẩm SaaS. Hãy ưu tiên các điểm chạm ảnh hưởng trực tiếp đến chuyển đổi:
- Form liên hệ / báo giá: input, validation, loading, success, error, retry.
- Nút CTA: hover, active, focus, disabled, loading.
- Menu và navigation: active page, dropdown, focus keyboard, mobile open/close.
- Card dịch vụ / sản phẩm: hover, selected, unavailable, link area rõ ràng.
- Checkout hoặc booking: trạng thái giỏ hàng trống, thanh toán lỗi, hết phiên, thành công.
- Dashboard hoặc khu vực khách hàng: loading dữ liệu, empty state, permission state, error state.
Điểm quan trọng là không xem UI state như “phụ kiện”. Nó là phần giao tiếp giữa hệ thống và người dùng. Một giao diện biết phản hồi đúng lúc sẽ làm người dùng yên tâm hơn, giảm thao tác sai và tăng khả năng hoàn tất hành động.
Nếu website hiện tại của bạn có form, CTA hoặc luồng đặt hàng nhưng người dùng thường bỏ dở, WebsiteHCM có thể kiểm tra nhanh các điểm nghẽn về UI states, UX và chuyển đổi. Bạn có thể gửi URL website hoặc trao đổi qua Zalo/Hotline 0346 844 259 để được định hướng cách tối ưu phù hợp.
Câu hỏi thường gặp về State-Based Design trong UI
State-Based Design khác gì Logic-Based Design?
State-Based Design tập trung vào việc người dùng nhìn thấy gì ở từng trạng thái giao diện. Logic-Based Design tập trung vào điều kiện, luồng xử lý và quy tắc nghiệp vụ phía sau. Hai phần này bổ trợ nhau: logic quyết định trạng thái nào xảy ra, còn UI state quyết định người dùng hiểu trạng thái đó như thế nào.
Có cần thiết kế tất cả trạng thái cho mọi component không?
Không cần làm quá mức cho mọi chi tiết nhỏ. Hãy ưu tiên component có tương tác, có dữ liệu động hoặc ảnh hưởng đến chuyển đổi: button, input, form, menu, card sản phẩm, checkout, filter, modal và dashboard.
Focus state có bắt buộc không?
Có. Focus state giúp người dùng bàn phím biết họ đang ở đâu trong giao diện. Đây là yêu cầu quan trọng trong accessibility và không nên bị xóa chỉ vì lý do thẩm mỹ.
Disabled state có nên chỉ làm màu xám không?
Không nên chỉ làm mờ. Nếu người dùng có thể thắc mắc vì sao không bấm được, hãy thêm helper text hoặc tooltip ngắn để giải thích điều kiện cần hoàn thành.
Empty state nên viết gì?
Empty state nên nói rõ tình huống hiện tại và gợi ý hành động tiếp theo. Ví dụ: “Bạn chưa có chiến dịch nào. Tạo chiến dịch đầu tiên để bắt đầu theo dõi hiệu quả.”
Làm sao quản lý state trong Figma mà không làm file thiết kế quá nặng?
Hãy dùng component variants, đặt tên thuộc tính rõ ràng và chỉ tạo trạng thái thật sự cần thiết cho vận hành. Với các trạng thái hiếm, có thể bổ sung bằng ghi chú hand-off thay vì nhân bản nhiều màn hình.
Kết luận: thiết kế trạng thái là thiết kế sự tử tế
State-Based Design không phải là bước làm đẹp thêm sau cùng. Nó là cách designer dự đoán những tình huống thật mà người dùng sẽ gặp: bấm nhầm, nhập sai, chờ tải, không có dữ liệu, mất kết nối hoặc dùng website bằng bàn phím. Khi mỗi trạng thái đều có phản hồi rõ ràng, giao diện trở nên đáng tin hơn.
Một UI tốt không chỉ trả lời “nhìn có đẹp không”, mà còn trả lời “khi có chuyện xảy ra, người dùng có biết phải làm gì tiếp theo không?”. Đó là sự khác biệt giữa giao diện tĩnh và trải nghiệm sản phẩm thật sự.
Nếu bạn đang chuẩn bị làm mới website, thiết kế landing page hoặc xây hệ thống giao diện nhất quán cho doanh nghiệp, có thể tham khảo dịch vụ thiết kế website chuyên nghiệp của WebsiteHCM để được tư vấn theo hướng UX, SEO và chuyển đổi ngay từ đầu.
Đoàn Trình Dục là Giảng viên Khoa Công nghệ Thông tin tại Đại học Công nghệ Sài Gòn (STU), với hơn 10 năm kinh nghiệm thực chiến trong các lĩnh vực Mạng máy tính, Marketing Online, SEO và Bảo mật hệ thống.
Với nền tảng sư phạm và kinh nghiệm tư vấn cho nhiều doanh nghiệp, thầy chuyên sâu vào việc xây dựng các giải pháp kỹ thuật số toàn diện và hiệu quả.

