Component
74 primitive, mỗi cái cài lẻ được bằng một lệnh. Mọi component chỉ đọc semantic token — đổi preset là đổi toàn bộ giao diện.
Form (21)
- ButtonButton and link-button. Sizes read the density tokens, so the same code renders compact in ERP and roomy in e-learning.
- CheckboxHộp kiểm dựa trên Radix Checkbox với trạng thái đã chọn, chưa chọn và không xác định.
- CodeEditorTrình soạn mã CodeMirror: tô cú pháp HTML, số dòng, gập khối, readOnly thật. Màu cú pháp đọc từ token nên đổi theo preset. Chỉ cài khi cần — CodeMirror không lọt vào dự án không dùng.
- ComboboxÔ chọn có tìm kiếm (Popover + Command + Button), generic theo kiểu giá trị, hỗ trợ xoá lựa chọn và tuỳ chọn bị vô hiệu hoá.
- ComboboxCreatableCombobox có thêm dòng "Tạo ..." khi ô tìm kiếm không khớp lựa chọn nào: gọi onCreate với đúng chữ đã gõ, chờ được round-trip lên server (có trạng thái đang tạo), tạo hỏng thì giữ nguyên chữ và báo lỗi. Dùng chung kiểu option với combobox.
- FileUploadVùng kéo thả kèm danh sách tệp, tiến trình từng tệp và chặn theo type/size. Không tự upload - trả tệp đã nhận cho dự án và vẽ tiến trình dự án báo về; tệp bị từ chối được báo chứ không nuốt.
- FormBộ khung biểu mẫu kết hợp react-hook-form và zod, cung cấp Form/FormField/FormItem/FormLabel/FormControl/FormDescription/FormMessage và hook useFormField với liên kết ARIA tự động.
- ImageCropperCắt và thu nhỏ ảnh ngay trên trình duyệt trước khi upload: vùng chọn kéo/resize được, khoá tỉ lệ tuỳ chọn, giới hạn cạnh dài, trả về File cho dự án tự gửi đi. Không thêm dependency nào - vùng cắt là một hình chữ nhật cộng một lệnh drawImage.
- InputTrường nhập liệu văn bản; chiều cao và khoảng đệm đọc từ token mật độ, hỗ trợ trạng thái lỗi qua aria-invalid.
- Input OTPTrường nhập mã OTP nhiều ô dựa trên thư viện input-otp, kích thước ô đọc từ token mật độ.
- LabelNhãn cho trường biểu mẫu dựa trên Radix Label, tự động làm mờ khi điều khiển liên kết bị vô hiệu hoá.
- NumberInputÔ nhập số kèm nút giảm/tăng ở chiều cao density. Không nhầm với stepper - cái đó là chỉ báo tiến trình nhiều bước cho wizard.
- Radio GroupNhóm nút chọn một dựa trên Radix Radio Group.
- RichTextTrình soạn thảo TipTap kèm toolbar dựng sẵn: 7 nhóm nút (định dạng, tiêu đề, danh sách, căn lề, liên kết, lịch sử, media), đọc/ghi HTML, chèn ảnh theo URL hoặc upload qua onImageUpload, nhúng YouTube. Chỉ cài khi cần — TipTap không lọt vào dự án không dùng.
- SaveBarThanh dính ở đáy trang cài đặt: số thay đổi chưa lưu, "Hoàn tác" và "Lưu tất cả thay đổi (n)". Không có thay đổi thì vô hiệu hoá chứ không ẩn, để trang không nhảy.
- SelectHộp chọn dựa trên Radix Select, hỗ trợ hai kích thước và đọc token mật độ cho chiều cao trigger.
- SliderThanh trượt chọn giá trị dựa trên Radix Slider, hỗ trợ nhiều điểm kéo.
- SwitchCông tắc bật/tắt dựa trên Radix Switch.
- TextareaVùng nhập văn bản nhiều dòng, tự co giãn theo nội dung và đọc token mật độ cho chiều cao tối thiểu.
- ToggleNút hai trạng thái bật/tắt, có biến thể default và outline, ba cỡ đọc từ token mật độ.
- ToggleGroupNhóm toggle chọn một hoặc nhiều. spacing=0 cho segmented control liền khối, spacing>0 tách rời — thay được cả segmented, seg-toggle lẫn alignment-toggle mà dự án hay tự viết.
Overlay (10)
- Alert DialogHộp thoại xác nhận bắt buộc phản hồi (Radix Alert Dialog), nút hành động dùng lại buttonVariants.
- CommandBảng lệnh tìm kiếm nhanh (bọc cmdk); CommandDialog kết hợp dialog để dùng như command palette.
- Context MenuMenu ngữ cảnh khi chuột phải (item, checkbox, radio, submenu) từ Radix Context Menu; chiều cao mục đọc token mật độ.
- DialogHộp thoại modal dùng Radix Dialog, với overlay và nội dung theo thang z-index modal của reno.
- DrawerBảng kéo lên từ dưới cho thao tác trên di động, bọc thư viện vaul.
- Dropdown MenuMenu thả xuống đầy đủ (item, checkbox, radio, submenu) từ Radix Dropdown Menu; chiều cao mục đọc token mật độ.
- Hover CardThẻ xem trước hiện khi di chuột vào trigger (Radix Hover Card).
- PopoverLớp phủ nổi neo theo trigger (Radix Popover) cho nội dung tương tác ngắn.
- SheetBảng trượt vào từ cạnh màn hình (Radix Dialog), hỗ trợ bốn hướng top/right/bottom/left.
- TooltipChú giải nổi khi di chuột/focus vào trigger (Radix Tooltip).
Layout (10)
- AccordionDanh sách mục có thể mở/thu gọn dựa trên Radix, kèm biểu tượng mũi tên xoay.
- Aspect RatioGiữ tỉ lệ khung hình cố định cho nội dung con, dựa trên Radix Aspect Ratio.
- CardBề mặt nội dung nổi có tiêu đề, hành động và chân trang; dùng bg-card/text-card-foreground.
- CarouselSlider dựng trên Embla: ngang/dọc, điều khiển bằng bàn phím, nút Trước/Sau đổi nhãn qua prop. Chỉ cài khi cần — Embla không lọt vào dự án không dùng.
- CollapsibleVùng nội dung có thể ẩn/hiện đơn giản, không có phần trang trí riêng.
- PageHeaderĐầu trang của một màn hình quản trị: breadcrumb tuỳ chọn, tiêu đề, dòng phụ, rồi bộ lọc trang và nút chính ở bên phải. Vị trí các phần cố định theo admin-layout-standard §2.3.
- ResizableBố cục nhiều khung có thể kéo giãn, dựa trên react-resizable-panels v4 (Group/Panel/Separator).
- Scroll AreaVùng cuộn có thanh cuộn tuỳ biến, dựa trên Radix Scroll Area.
- SeparatorĐường phân cách ngang hoặc dọc, dùng bg-border.
- TabsĐiều hướng dạng thẻ tab dựa trên Radix; hai biến thể segmented (mặc định) và underline cho object page; chiều cao TabsList đọc density-control-height.
Data (18)
- AttentionCardThẻ "Cần bạn xử lý": nhãn trạng thái, meta bên phải, một con số lớn, một dòng giải thích và một nút. Mức độ (warning hoặc destructive) tô viền và nền bằng token.
- AudioPlayerTrình phát audio kèm thanh điều khiển: phát/dừng, seek, thời lượng, âm lượng, tốc độ. Không lưu tiến độ - phát onProgress/onEnded để dự án tự lưu, cùng giao kèo với video-player.
- AvatarẢnh đại diện với ảnh, chữ viết tắt dự phòng và ba cỡ đọc token density, đồng bộ chiều cao với Button.
- BulkActionBarThanh thao tác hàng loạt phía trên danh sách khi có dòng được chọn: "Đã chọn N", các nút, "Bỏ chọn"; thêm banner chọn tất cả kết quả khớp bộ lọc khi đã chọn cả trang. Không có dòng nào được chọn thì không vẽ gì.
- CalendarLịch chọn ngày dựa trên react-day-picker v10, mặc định locale tiếng Việt (date-fns/locale/vi). Nút điều hướng tái sử dụng buttonVariants.
- ChartBiểu đồ cột/đường/vùng trên recharts. API khai báo (data + series), không có type recharts trong props. Màu series đọc --chart-1..5 nên đổi theo preset và light/dark. Chỉ cài khi cần — dự án không dùng biểu đồ không dính recharts.
- DataGridGrid ảo hoá cho admin/ERP: 10k+ dòng, server-side pagination/sort/filter, ghim/resize/ẩn cột, chọn dòng xuyên trang, empty/loading/error có sẵn. Chỉ cài khi cần — dự án nhẹ dùng @reno/table.
- DataGrid ToolbarThanh công cụ cho DataGrid: tìm kiếm có debounce, chip bộ lọc đang bật, ẩn/hiện cột, xuất dữ liệu. Item riêng để màn hình không cần thì không phải cài.
- Date PickerDatePicker (một ngày) và DateRangePicker (khoảng ngày), ghép từ Popover + Calendar + Button, định dạng và locale mặc định tiếng Việt.
- KvRowDòng nhãn — giá trị cho trang chi tiết. Dựng bằng <dl> nên screen reader đọc thành từng cặp; KvList tự vẽ đường kẻ giữa các dòng, không cần CSS từ dự án.
- PaginationPhân trang không phụ thuộc next/link, tái sử dụng buttonVariants. Nhãn Trước/Sau và mô tả trợ năng có tiếng Việt mặc định, ghi đè được qua props.
- PermissionMatrixMa trận phân quyền: vai trò là cột, quyền là hàng nhóm theo tài nguyên, mỗi ô một checkbox; badge "Phạm vi khác"; hàng tiêu đề và cột đầu dính; nút Tạo vai trò, Hoàn tác, Lưu tất cả thay đổi (n). Quyền ngụ ý (Toàn quyền) được giữ đúng hai chiều.
- QuotaWidgetĐồng hồ hạn mức hoặc điểm còn lại: nhãn, số còn lại trên tổng, thanh tiến độ, dòng chú thích và một hành động. Nằm cuối sidebar và trong menu người dùng.
- RowActionsCột "Hành động" của danh sách: tối đa 4 hành động dùng nhiều nhất là nút icon có tooltip, phần còn lại nằm trong menu "⋯" (chỉ có khi có hơn 4). Hành động phá huỷ trong menu mang màu destructive và hỏi xác nhận.
- StatCardÔ KPI: nhãn, một con số, và chiều biến động. Có trạng thái loading, có biến thể bấm được (semantics button + bàn phím). Hướng mũi tên và màu tách riêng — churn tăng là tin xấu.
- TableBảng dữ liệu tĩnh cho danh sách CMS/e-learning. Không dùng TanStack — tính năng lưới nặng thuộc @reno/data-grid; chiều cao dòng và đệm ô đọc token density.
- TimelineDòng thời gian dọc: lịch sử đơn, audit log, nhật ký tư vấn, bảng hoạt động. Dot tô theo intent, có slot actions cho từng mục. Dựng bằng <ol>.
- VideoPlayerTrình phát HLS kèm thanh điều khiển dựng sẵn: seek, âm lượng, tốc độ, chọn chất lượng, toàn màn hình, 5 phím tắt. Không lưu tiến độ — phát onProgress/onEnded để dự án tự lưu. Chỉ cài khi cần — hls.js không lọt vào dự án không dùng.
Feedback (8)
- AlertThông báo nổi bật với các biến thể default/destructive/success/warning/info dùng token trạng thái.
- BadgeNhãn nhỏ với các biến thể default/secondary/destructive/outline/success/warning/info, hỗ trợ asChild.
- EmptyStateTrạng thái rỗng dùng chung: icon, tiêu đề, mô tả, hành động. Không có chuỗi mặc định — mỗi màn hình tự đặt câu của mình. DataGrid dùng chính component này.
- ErrorStateTrạng thái lỗi dùng chung: icon, tiêu đề, mô tả, và nút thử lại (nhãn tiếng Việt, đổi được qua prop). DataGrid dùng chính component này.
- ProgressThanh tiến trình dựa trên Radix Progress, phần chỉ báo dùng bg-primary.
- SkeletonKhối giữ chỗ khi đang tải, dùng bg-accent kết hợp hiệu ứng animate-pulse.
- SonnerBọc Toaster của sonner, không phụ thuộc next-themes; màu sắc ánh xạ qua CSS variable API của sonner theo token reno.
- SpinnerChỉ báo đang tải nhỏ gọn, role=status, kích thước đọc density token, màu theo currentColor.
Nav (7)
- BreadcrumbĐiều hướng breadcrumb không phụ thuộc router. BreadcrumbLink nhận asChild để gắn next/link hoặc thẻ <a> tuỳ dự án.
- MenubarThanh menu kiểu ứng dụng desktop, đầy đủ menu con, checkbox và radio item của Radix. Lớp nổi dùng z-index token --z-dropdown.
- Navigation MenuMenu điều hướng cấp cao với viewport và indicator của Radix. Lớp nổi dùng z-index token --z-dropdown.
- SidebarThanh điều hướng ứng dụng đầy đủ tính năng: thu/phóng, chế độ icon, sheet trên mobile, tooltip khi thu gọn, lưu trạng thái qua cookie. Menu item dùng asChild thay vì gắn cứng router.
- SiteBrandNhận diện thương hiệu cho header và footer: logo (URL ảnh hoặc SVG) kèm wordmark, liên kết về trang chủ. Biến thể default/logo/wordmark, cỡ sm/default/lg theo density token; logo lỗi hoặc thiếu thì hiện wordmark. asChild để gắn Link của router.
- StepperChỉ báo tiến trình nhiều bước: checkout, onboarding, wizard import. Ngang hoặc dọc. Dựng bằng <ol> + aria-current=step, trạng thái từng bước có chữ chứ không chỉ có màu. Mọi nhãn qua prop labels.
- UserMenuPopover dưới avatar ở header: danh tính, thẻ hạn mức, các mục tài khoản, ngôn ngữ, giao diện Sáng/Tối/Auto, trợ giúp, đăng xuất. Nội dung và thứ tự cố định theo admin-layout-standard §3.