KIếN THứC WEBSITE › UI/UX DESIGN

Component library là gì: stack chuẩn 2026, governance và metric đo adoption

Component library là gì: stack chuẩn 2026, governance và metric đo adoption

Component library là code-side của design system: gói các UI component (Button, Input, Modal, Card, …) viết bằng React/Vue/Svelte/Web Components, đóng gói thành npm package private hoặc public, tái sử dụng cho nhiều app trong cùng tổ chức.

Khác với design system tổng thể (4 lớp gồm token, component, pattern, guideline), component library tập trung lớp component thực thi được — có code, có Storybook docs, có unit test, có visual regression test, có version semver, có changelog. Stack chuẩn 2026 cho team mid: Vite library mode + tsup bundler + Tailwind v4 + Radix UI primitives + TypeScript strict + Vitest + Storybook 8 + Chromatic + Changesets + npm private registry. Bài này giải thích chi tiết stack, governance PR, cách distribute qua monorepo hoặc separate repo, build từ đầu vs fork Shadcn pattern, và metric đo adoption.

Vòng đời component library từ source code, build CI, publish npm tới consumer apps
Vòng đời component library từ source code, build CI, publish npm tới consumer apps

Component library trong kiến trúc design system

Component library là một sản phẩm phần mềm independent — có owner, version, changelog, user (internal team), bug tracker, roadmap. Output là npm package mà các app trong tổ chức consume qua npm install @org/ui. Khác biệt cốt lõi với “thư viện UI bừa bãi”: có quy trình release rõ ràng, có test coverage, có documentation, có deprecation policy.

Trong kiến trúc design system 4 lớp, component library chiếm lớp 2 (Components) — ngay trên foundation token và dưới pattern + guideline. Component library tiêu thụ token từ design token package (vd @org/design-tokens) và expose API React/Vue cho consumer apps. Phía designer tương ứng là Figma library — Code Connect map 1-1 component Figma với component code thật, đảm bảo mockup design sync với production runtime.

Component library có thể serve nhiều consumer khác stack: web app React (Marketing site Next.js, dashboard admin Vite), mobile web Astro, embedded widget cho partner. Nếu cần native iOS/Android, component library chỉ stay tại web layer — mobile native dùng package riêng (SwiftUI cho iOS, Jetpack Compose cho Android) consume cùng design token nhưng implement khác.

Mature component library 2026 thường có 25-60 component cho team mid (Shopify Polaris có 50+, Atlassian DS 60+, Adobe Spectrum 70+). Số lượng không phản ánh quality — quan trọng hơn là: API design consistent, accessibility chuẩn WCAG AA, performance bundle size tree-shakeable, documentation đầy đủ với usage example chạy được.

Stack chuẩn 2026 — chi tiết từng layer

Stack dưới đây Web22 dùng cho 8+ project component library production từ 2024, đã verify ổn định cho team 2-15 frontend dev. Stack tối ưu cho React (đa số use case), nếu Vue/Svelte thay equivalent component (Radix → Headless UI cho Vue, Storybook hỗ trợ cả 2 framework).

Build tool — Vite library mode + tsup. Vite library mode build component sang ESM + CJS, tree-shakeable, source map đầy đủ. tsup bundler cho package nhỏ hơn (2-3 component utility). Cấu hình rollup external React + react-dom (peer dep, không bundle). Output thường 50-300KB tổng cho library 30 component, với consumer chỉ cần phần dùng (vd consumer dùng 5/30 component, bundle final 30-50KB).

Styling — Tailwind v4 + CSS Variables (token). Tailwind v4 (2024) hỗ trợ CSS variable native, integration với token dễ. Pattern: token JSON build qua Style Dictionary ra tailwind.config.js với theme extend, Tailwind generate utility class semantic (bg-primary, text-muted, p-md). Component dùng utility class, không inline style. Detail xem Tailwind làm design system. Alternative: CSS Modules + PostCSS, hoặc Vanilla Extract — nhưng Tailwind v4 đang dominant 2026.

Headless primitives — Radix UI. Radix UI cung cấp behavior + accessibility primitives (Dialog, Dropdown, Popover, Tooltip, Select, Checkbox, …) hoàn toàn unstyled. Component library wrap Radix primitive + style theo Tailwind/token. Lợi: accessibility built-in (focus management, keyboard nav, ARIA attribute, screen reader announcement đầy đủ), tránh reinvent wheel. Tham khảo radix-ui.com. Alternative: Headless UI (Tailwind team), Ariakit, React Aria (Adobe).

Type system — TypeScript 5.x strict mode. Bắt buộc strict cho library — tránh edge case runtime. Setup tsconfig strict: true, noUncheckedIndexedAccess: true, exactOptionalPropertyTypes: true. Export type definitions với declaration map cho IDE jump-to-source.

Test — Vitest + Testing Library + axe-core. Vitest fast hơn Jest 5-10 lần, native ESM, share config với Vite. Testing Library cho user-centric test (query by role, label, text — không phải implementation detail). axe-core + jest-axe cho automated accessibility test mỗi component. Coverage target 80%+ statement.

Visual — Storybook 8 + Chromatic. Mỗi component có 3-7 story (default, all variants, edge case). Chromatic chạy visual regression test mỗi PR — diff screenshot, fail nếu mismatch >0.1%. Free tier Chromatic 5000 snapshot/tháng đủ cho team mid. Detail xem storybook.js.org.

Versioning — Changesets + semver. Changesets là tool quản lý changelog + version trong monorepo. Mỗi PR thêm “changeset” file mô tả thay đổi và bump type (patch/minor/major). Khi merge main, GitHub Actions auto release: gom changeset → bump version → publish npm → tag git → tạo GitHub Release.

Registry — npm private (Verdaccio/Bytesafe) hoặc npm pro. Registry private cho component library nội bộ. Verdaccio self-host miễn phí, Bytesafe SaaS 10-50 USD/tháng. npm pro plan (7 USD/user/tháng) là alternative chính thức nếu đã dùng GitHub.

Cấu trúc repo — monorepo vs separate

Hai pattern phổ biến cho component library: monorepo (component library cùng repo với consumer apps) và separate repo (component library standalone, consumer install qua npm). Mỗi pattern có trade-off — chọn theo team size và workflow.

Pattern 1 — Monorepo (recommend cho team < 30 dev). Setup pnpm workspaces hoặc Turborepo, structure: packages/ui/ (component library), packages/tokens/ (design token), packages/icons/, apps/marketing/, apps/dashboard/, apps/storybook/. Lợi: dev có thể edit component và test trong consumer app cùng lúc, không phải publish-then-install loop, build cache shared (Turbo). Hạn chế: repo nặng (clone chậm), CI complexity tăng, không phù hợp khi consumer apps không cùng tổ chức.

Pattern 2 — Separate repo (recommend cho enterprise hoặc multi-team). Component library trong repo org/design-system-ui riêng. Consumer apps trong các repo khác install qua pnpm add @org/[email protected]. Lợi: ownership rõ ràng, release cadence độc lập, repo nhẹ, phù hợp team distributed. Hạn chế: dev iterate component chậm hơn (publish + install loop), cần npm link hoặc Verdaccio local cho dev experience tốt.

Web22 default monorepo cho khách startup-mid (5-25 dev), separate repo khi khách là enterprise (50+ dev) hoặc khi DS phục vụ multi-tenant (mỗi tenant 1 brand variant).

Tooling cho monorepo: pnpm workspaces (nhẹ, fast), Turborepo (build cache + task orchestration), Nx (alternative Turbo, mạnh về graph), Lerna (legacy, đang faded out 2024+). Recommend pnpm + Turbo cho 2026.

Governance — PR review + RFC + deprecation

Component library production cần governance để tránh chaos khi nhiều dev contribute. Governance không phải bureaucracy — chỉ là quy tắc minimum để đảm bảo quality. Web22 áp dụng 4 quy tắc dưới cho mọi project DS production.

Quy tắc 1 — Mọi component PR phải có Storybook story + unit test + screenshot Chromatic. CI fail nếu PR add component mới mà thiếu 3 thứ này. Story phải cover ≥3 variant chính (default, edge case data, error state). Test phải cover happy path + 1-2 edge case + accessibility check. Screenshot Chromatic auto-generate trong CI.

Quy tắc 2 — Breaking change phải có RFC trước. RFC (Request For Comments) là issue GitHub mô tả: vấn đề hiện tại, proposal thay đổi, alternative đã consider, migration path cho consumer. RFC mở 1-2 tuần cho team comment, ≥1 maintainer + 1 designer approve mới merge. Sau merge, breaking change ship qua MAJOR bump + 6 tuần deprecation notice trong consumer apps trước khi remove API cũ.

Quy tắc 3 — Release cadence cố định. Patch on-demand (bug fix), minor mỗi 2 tuần (feature mới không break), major mỗi 6-12 tháng (pre-announce 4 tuần). Predictable cadence giúp consumer apps schedule update, tránh fatigue khi DS update liên tục mỗi ngày.

Quy tắc 4 — Telemetry usage opt-in. Setup metric đo adoption: % component import từ DS package vs custom (target 80%+ sau 6 tháng), số PR đóng góp từ team consumer (dấu hiệu DS được care, không bị bypass), time-to-add-feature trước-sau (target tăng tốc 20-40% sau 12 tháng).

4 quy tắc này tốn 2-3 tuần setup ban đầu (RFC template, PR template, CI workflow) nhưng tiết kiệm 50-100 giờ debugging và fix-up sau 6-12 tháng. ROI dương rõ ràng cho team >5 dev contribute DS.

Build từ đầu vs fork Shadcn UI

Year 2024 ra đời pattern mới: Shadcn UI không phải npm package mà là copy-paste codebase. Dev chạy CLI npx shadcn-ui add button, code Button.tsx được copy vào project, dev tự own + customize. Pattern này đã dominant 2025-2026 — nhiều project mới chọn Shadcn thay vì build component library traditional.

Lợi của Shadcn pattern: không có dependency lock-in (code own bởi project, không update theo upstream tự động), customize 100% (sửa source code thẳng, không phải override qua prop hoặc CSS hack), bundle size minimal (chỉ component dùng, không phải import cả library). Phù hợp: team có 1-3 product surface, không cần share component cross-team, brand visual unique cần customize sâu.

Hạn chế Shadcn pattern: mỗi project có codebase Button riêng → không sync khi sửa bug → drift cross-project. Không có version semver — nếu Shadcn upstream cải Button, project không tự update, phải copy-paste lại manual. Không phù hợp khi 5+ app trong tổ chức cần dùng cùng component.

Web22 recommend Shadcn pattern khi: project là 1 web app duy nhất, team 1-5 dev, brand visual unique, không có roadmap multi-app trong 12 tháng tới. Recommend traditional npm package khi: ≥3 consumer apps, ≥10 dev, cần governance và shared component cross-team.

Combo lai cũng phổ biến: fork Shadcn làm base (tận dụng Radix + Tailwind), nhưng publish thành npm package nội bộ (có version) thay vì để mỗi project copy. Đây là pattern Web22 dùng cho ~40% project mid-size 2025-2026 — best of both worlds. Detail xem bài Shadcn UI làm design system.

Component library notable công khai

Audit component library công khai giúp benchmark API design, accessibility, documentation pattern. Dưới đây là 6 library notable năm 2026, mỗi library có triết lý riêng — không copy 100% nhưng nên tham khảo trước khi setup mới.

MUI (Material UI) — implement Material Design cho React, mature từ 2014, 100+ component, ecosystem khổng lồ (X-Data Grid, X-Date Pickers, …). Phù hợp: app B2B/admin dashboard, team không có designer (Material Design làm sẵn). Hạn chế: bundle size lớn (MUI core ~150KB gzipped), customize sâu khó (Material Design opinionated).

Chakra UI — focus accessibility + DX, 60+ component, system-based styling (sx prop, theme tokens). Phù hợp: app modern, team trẻ. Hạn chế: maintainer chuyển focus sang Panda CSS, Chakra v3 chậm release.

Mantine — feature-rich (100+ component + hooks library), TypeScript first, accessibility tốt. Phù hợp: app dashboard cần full feature, không muốn mix nhiều library. Hạn chế: opinionated styling (CSS-in-JS), bundle size khá lớn.

Radix Themes — sibling của Radix UI primitives, nay có styled component opinionated. Lightweight (~50KB), accessible-first. Phù hợp: project mới muốn baseline tốt, customize sau qua CSS variable.

Shadcn UI — pattern copy-paste đã đề cập. Phù hợp: indie hacker, project nhỏ-mid, team muốn own code 100%.

Ant Design — Alibaba, focus enterprise B2B Trung Quốc, 70+ component, có Pro variant + Mobile variant. Phù hợp: app enterprise truyền thống. Hạn chế: design language cũ (looks dated 2026), bundle lớn.

Cho dự án WordPress Block Editor, ecosystem khác hoàn toàn — dùng @wordpress/components (Gutenberg components). Các component đã tích hợp với block editor, accessible, sync với WP design language. Detail về custom block FSE giúp scope đúng phần block UI nào dùng @wordpress/components.

Storybook + documentation site

Documentation là lifeline của component library — thiếu docs hoặc docs kém thì component không được adopt, dù code chất lượng tốt. Storybook là tool de facto cho component docs 2026, dùng bởi 70%+ DS công khai (theo audit Web22 các DS open-source).

Setup Storybook 8: npx storybook@latest init trong package packages/ui/. Mỗi component có file Component.stories.tsx với 3-7 story:

  • Default: render component với props mặc định, không kèm interaction.
  • All Variants: render mọi variant trong 1 view (vd Button hiển thị 5 variant × 3 size = 15 instance), giúp visual review nhanh.
  • Interactive: story có Storybook Args để dev play với props qua panel UI.
  • Edge Case Data: empty state, very long text, loading state, error state.
  • Composition: component trong context page thật (vd Button trong Form, Card trong Grid).

Bổ sung MDX docs cho mỗi component: usage guideline, do/don’t, accessibility note, design rationale. Storybook Docs addon render MDX trong tab “Docs” cùng với story. Pattern này đã chuẩn từ Storybook 7.

Visual regression test qua Chromatic (do Storybook team): mỗi PR Chromatic chạy snapshot tất cả story, compare với baseline, fail nếu pixel diff >0.1%. Reviewer accept change hoặc reject. Free tier 5000 snapshot/tháng đủ cho team mid (typical 100 story × 50 PR/tháng = 5000 snapshot).

Deploy Storybook lên domain riêng (vd design.example.com): build Storybook ra static folder, deploy Vercel/Netlify/Cloudflare Pages. Add custom domain, embed search (Algolia DocSearch free cho open-source). Documentation site là entry point cho team consumer — bookmark trong Slack channel design-system, link trong onboarding doc.

Metric đo adoption — DS có thực sự được dùng?

Component library investment có ROI âm nếu không được adopt. Setup metric đo adoption sớm, tránh trường hợp 6 tháng sau audit thấy ½ team vẫn dùng component custom riêng.

Metric 1 — % import từ DS vs custom. Chạy script grep mỗi tháng đếm số import từ @org/ui vs số component custom inline trong consumer apps. Target: 80%+ component dùng DS sau 6 tháng go-live. Nếu <50% sau 3 tháng, audit lý do dev bypass DS — thường do component thiếu prop, perf kém, hoặc docs khó tìm.

Metric 2 — Số PR contribute vào DS từ team consumer. Dấu hiệu DS được care, không phải bị bypass. Target: 5-10 PR/tháng từ team consumer (không phải DS owner). Ít hơn → consumer không invest, có thể là dấu hiệu DS bị treat như “thuộc team khác”.

Metric 3 — Time-to-add-feature trước-sau. Đo subjective qua survey dev mỗi quý: “build feature mới mất bao lâu so với 6 tháng trước?”. Target: tăng tốc 20-40% sau 12 tháng. Đo rough vì có nhiều factor khác (dev mới, complexity feature) nhưng trend dài hạn vẫn meaningful.

Metric 4 — Bundle size growth của consumer apps. DS tốt giúp consumer apps share code, bundle size tăng chậm dù feature growth nhanh. Track qua Bundlewatch hoặc Bundle Buddy mỗi PR. Bad signal: consumer app bundle tăng 20-30% sau 6 tháng adopt DS — có thể do tree-shake không hoạt động, hoặc consumer import cả library thay vì specific component.

Metric 5 — Adoption rate component mới. Khi release component mới (vd Toast component), track sau 4 tuần: bao nhiêu % consumer apps đã import? Target: ≥50% sau 4 tuần cho component generic, ≥80% sau 12 tuần. Adoption rate thấp → component không cần thiết, hoặc API kém, hoặc thiếu marketing internal.

Setup dashboard metric trong Notion/Linear/PostHog với 5 metric trên, review hàng tháng cùng DS team. Decision-making về roadmap dựa trên data, không guess feeling.

FAQ

Component library có cần publish public lên npm không?

Không bắt buộc. Đa số component library tổ chức là private (npm private registry, GitHub Packages, hoặc Verdaccio self-host). Publish public chỉ khi: open-source DS public (như Shadcn), hoặc partner cần access (vd shop dùng DS của Marketplace). Cost npm pro plan 7 USD/user/tháng cho private package, hoặc Verdaccio self-host miễn phí.

Stack React vs Vue vs Web Components — chọn cái nào?

React dominant 2026, đa số DS công khai chọn React first. Vue có ecosystem nhỏ hơn nhưng vẫn solid (Vuetify, PrimeVue). Web Components (Lit) là lựa chọn neutral framework — phù hợp khi consumer apps mix multiple framework (React + Vue + Angular trong cùng tổ chức), library Web Component dùng cho cả 3. Hạn chế Web Components: form integration chưa hoàn hảo, accessibility tốn effort hơn React + Radix. Recommend: chọn theo stack consumer apps chính, đa số case React.

Có cần build mobile native iOS/Android component cùng web không?

Phụ thuộc roadmap. Nếu sản phẩm mobile native là core (vd app delivery, fintech), nên có DS cross-platform: token JSON shared (Style Dictionary build CSS + Swift + XML), component implement riêng cho mỗi platform (React/Vue cho web, SwiftUI cho iOS, Jetpack Compose cho Android). Effort cao gấp 2-3 lần web-only. Nếu mobile chỉ là phụ (web responsive đủ), skip native, focus web. Quy tắc rough: mobile native >30% revenue thì invest cross-platform DS, <10% revenue thì skip.

Bundle size component library bao nhiêu là acceptable?

Library tổng size không quan trọng bằng tree-shake hiệu quả — consumer chỉ pay cost cho component dùng. Target: library 30-50 component có tổng bundle 100-300KB gzipped, nhưng consumer typical dùng 5-10 component → final bundle 30-80KB. Test bằng npm install library vào project demo, build production, đo bundle. Nếu consumer dùng 5 component mà bundle ≥100KB → tree-shake fail, fix import path hoặc dùng sideEffects: false trong package.json.

Có nên dùng CSS-in-JS như styled-components hay Tailwind?

2026 trend nghiêng Tailwind v4 + CSS variable, ít dùng CSS-in-JS runtime (styled-components, Emotion runtime). Lý do: CSS-in-JS runtime gây performance overhead (parse CSS at runtime), conflict với React Server Component (Next.js App Router), bundle size lớn hơn. Alternative tốt: Tailwind, Vanilla Extract, Panda CSS, CSS Modules. Cho component library mới setup 2026, Tailwind v4 + CSS vars là combo phổ biến nhất.

Storybook 8 vs Ladle vs Histoire — chọn cái nào?

Storybook 8 là default cho 70%+ DS — ecosystem lớn nhất (addon, Chromatic integration, MDX docs). Hạn chế: build chậm cho library lớn (Storybook v7 cải nhiều, v8 vẫn chậm hơn alternative). Ladle (do Uber) build nhanh hơn 5-10 lần, API gần như Storybook compatible — phù hợp library lớn 100+ component. Histoire cho Vue (Storybook hỗ trợ Vue nhưng Histoire native Vue tốt hơn). Recommend: Storybook 8 cho 90% case, switch Ladle khi build chậm gây pain.

Component library cho WordPress dùng như thế nào?

WordPress block editor đã có @wordpress/components (Button, Modal, ColorPicker, ToggleControl, …) — tận dụng đầu tiên thay vì build từ đầu. Custom block tự định nghĩa thường compose từ @wordpress/components. Cho theme front-end (không phải block editor), build component PHP/Twig hoặc dùng Carbon Fields macro. Stack hỗn hợp này khác hẳn React app — Web22 thường tách 2 layer DS riêng cho WordPress: layer admin block (React) + layer front-end theme (PHP/Carbon Fields).

Web22 build component library production cho khách startup tới enterprise, scope từ 15-60 component với stack chuẩn 2026 (Vite + Tailwind v4 + Radix + Storybook 8 + Chromatic + Changesets). Tham khảo /dich-vu/thiet-ke-ui-ux/design-system/ để xem scope chi tiết và combo build component library + Figma library + handoff training trong 4-12 tuần.