Bỏ qua tới nội dung
UI/UX Design· ·8 phút đọc

Dựng design system bằng shadcn/ui (hướng dẫn cho dự án React)

Nguyễn Quốc An
Dựng design system bằng shadcn/ui (hướng dẫn cho dự án React)
Cỡ chữ

Khi muốn có một hệ thống thiết kế (design system — bộ quy ước và component dùng chung cho cả sản phẩm) trên React, nhiều đội dừng lại ở câu hỏi quen thuộc: cài một thư viện UI có sẵn, hay tự dựng từ đầu? shadcn/ui đưa ra lựa chọn thứ ba, và đây là lý do nó được nhắc đến nhiều trong các stack React mới năm 2026.

shadcn/ui không phải thư viện component thông thường

Điểm khác biệt cốt lõi: shadcn/ui không phải một package bạn cài qua npm rồi import. Thay vào đó, bạn dùng dòng lệnh (CLI — công cụ chạy bằng câu lệnh trong terminal) để copy mã nguồn component thẳng vào thư mục dự án. Sau khi thêm, component như Button hay Dialog trở thành file của chính bạn, nằm trong repo của bạn.

Hệ quả rất lớn cho một design system:

  • Bạn sở hữu code. Muốn đổi bo góc, đổi cách xử lý trạng thái loading, gộp thêm logic riêng — bạn sửa thẳng file, không phải chờ bản phát hành của bên ngoài hay viết đè (override) chật vật.
  • Không bị khoá phiên bản. Một thư viện đóng gói nếu nâng cấp có thể đổi giao diện hàng loạt component ngoài ý muốn. Ở đây không có chuyện đó: code đã nằm trong dự án, bạn cập nhật khi nào bạn chọn.
  • Không phình bundle vô ích. Bạn chỉ copy đúng component cần dùng.

Theo tài liệu chính thức, shadcn/ui tự mô tả mình là “tập hợp component tái dùng để copy-paste vào ứng dụng”, chứ không phải một thư viện cài đặt. Phân biệt này quyết định cách bạn nghĩ về nó.

Sơ đồ ba lợi thế khi copy mã nguồn component shadcn/ui thẳng vào dự án thay vì cài package
Copy code vào dự án giúp bạn sở hữu code, không bị khoá phiên bản và không phình bundle.

Vì sao Radix + Tailwind là nền tốt cho design system tuỳ biến

shadcn/ui đứng trên hai lớp nền vững:

  • Radix UI lo phần primitive (component nguyên thuỷ — phần lõi xử lý hành vi và accessibility): quản lý focus, điều hướng bàn phím, vai trò ARIA cho dropdown, dialog, popover… Đây là phần khó và dễ làm sai nhất nếu tự viết. Radix làm sẵn, đúng chuẩn truy cập (accessibility — khả năng người khuyết tật dùng được).
  • Tailwind CSS lo phần trình bày bằng các lớp tiện ích (utility class). Nhờ vậy, giao diện một component nằm ngay trong markup, dễ đọc, dễ đổi.

Sự tách vai này là lý do shadcn/ui hợp làm nền cho design system riêng: phần hành vi đã chuẩn và ổn định (Radix), còn phần “nhìn thế nào” hoàn toàn nằm trong tay bạn (Tailwind + code bạn sở hữu). Bạn không phải đánh đổi giữa “đẹp theo ý mình” và “đúng chuẩn truy cập”.

Theme bằng CSS variables — trái tim của hệ thống

shadcn/ui dùng biến CSS (CSS variables) ghép với Tailwind để đặt token màu theo ngữ nghĩa. Thay vì gán màu cứng, component dùng các cặp token nền – chữ:

TokenVai trò
background / foregroundNền chung và chữ mặc định
primary / primary-foregroundHành động nhấn mạnh, màu thương hiệu
muted / muted-foregroundBề mặt phụ, chữ phụ trợ
destructiveHành động xoá, cảnh báo lỗi
border, input, ringViền, ô nhập, vòng focus

Vì mọi component đọc cùng bộ token này, đổi vài dòng biến CSS trong :root (và .dark cho dark mode) là cả hệ thống đổi theo, đồng nhất. Đây chính là tinh thần của design token làm đơn vị nhỏ nhất — một nguồn sự thật duy nhất cho màu, cỡ, khoảng cách. Bật chế độ này bằng tailwind.cssVariables: true trong components.json.

Sơ đồ bốn bước bắt đầu dựng design system bằng shadcn/ui từ khởi tạo đến mở rộng
Bốn bước từ khởi tạo CLI đến mở rộng dần thành design system riêng.

Cách bắt đầu

  1. Khởi tạo. Trong dự án React/Next.js đã có Tailwind, chạy:
    npx shadcn@latest init

    Lệnh này tạo file components.json (lưu cấu hình: đường dẫn, style, có dùng CSS variables hay không) và đặt sẵn các token CSS vào file global.

  2. Thêm component cần dùng. Ví dụ:
    npx shadcn@latest add button dialog input

    Mã nguồn các component này được copy vào thư mục của bạn (thường là components/ui).

  3. Đặt token thương hiệu. Mở file CSS global, sửa các biến như --primary, --radius sang giá trị brand của bạn. Toàn bộ component cập nhật theo.
  4. Mở rộng dần thành design system. Gói các component đã chỉnh thành tầng riêng, đặt quy ước đặt tên, tài liệu hoá. Từ năm 2026, shadcn 3.0 còn cho phép dựng registry (kho component riêng) để phân phối component nội bộ cho nhiều dự án qua chính CLI đó.

shadcn/ui khác gì so với “dựng design system bằng Tailwind”?

Hai cách dễ bị nhầm. Dựng bằng Tailwind thuần là bài rộng hơn: bạn tự định nghĩa toàn bộ token, tự viết mọi component từ con số không, toàn quyền nhưng tốn công và phải tự lo accessibility. shadcn/ui là một điểm khởi đầu cụ thể trên chính nền Tailwind đó — cho sẵn primitive đã chuẩn (Radix) và bộ component mẫu đã đẹp, rồi bạn tuỳ biến. Nếu bạn cần so sánh đường đi tổng quát hơn, xem bài dựng design system bằng Tailwind; còn bài này nói riêng về shadcn/ui. Cả hai đều là cách hiện thực hoá khái niệm design system chứ không phải khái niệm tách biệt.

Ở góc thực chiến, web22.dev tự chạy một hệ thống thiết kế riêng (font Inter Tight, màu coral, component tái dùng trong theme), nên Web22 nhìn cách tiếp cận “sở hữu code” này rất hợp với những dự án muốn brand riêng mà vẫn nhanh. Nếu bạn đang cân nhắc dựng nền giao diện bài bản, tham khảo dịch vụ xây design system của Web22.

Câu hỏi thường gặp

shadcn/ui có miễn phí không?

Có. Đây là dự án mã nguồn mở, bạn dùng và copy code thoải mái cho dự án thương mại.

Dùng shadcn/ui có cần biết Tailwind không?

Nên có. Vì giao diện component viết bằng utility class của Tailwind, bạn cần đọc và sửa được Tailwind để tuỳ biến hiệu quả.

Component đã copy thì cập nhật sao?

Vì code thuộc về bạn, không có “tự động cập nhật”. Khi cần bản mới của một component, bạn chạy lại lệnh add hoặc chỉnh tay — đổi lại là bạn kiểm soát hoàn toàn, không bị thay đổi ngoài ý muốn.

Cần làm web?

Dịch vụ liên quan
tới chủ đề bài này.

Tất cả dịch vụ
Đọc tiếp

Bài viết
cùng chủ đề.

Tất cả bài viết