FileDrop
Mẫu chuẩnVùng kéo-thả và chọn tệp cho tài liệu Tier-1 (PDF, DOCX, XLSX, CSV, TXT, MD). Bốn trạng thái: idle, dragover (tự quản bởi component khi kéo tệp vào), uploading và error (do host điều khiển qua prop state). Không tự gọi server -- host nhận File[] qua onFiles và tự quyết định tải lên đâu.
Playground
Chọn "uploading" để thấy Progress, "error" để thấy thông báo lỗi. Kéo một tệp thật vào ô để thấy trạng thái dragover (component tự quản, không qua prop state).
Chưa chọn tệp nào.
import { FileDrop } from "@nexobox/ui";
<FileDrop
accept={[".pdf", ".docx", ".xlsx", ".csv", ".txt", ".md"]}
maxBytes={20 * 1024 * 1024}
state="idle"
onFiles={(files) => handleFiles(files)}
>
Kéo tệp vào đây hoặc bấm để chọn
</FileDrop>Bài toán
K3a cần một điểm nạp tài liệu duy nhất cho cả bảy định dạng Tier-1. Không có primitive kéo-thả nào trong packages/ui trước brief này -- mỗi màn hình tải tệp tự chế lại cùng một ô viền đứt nét.
Khi nào sử dụng
Nên dùng
Trang "Tài liệu" của Crew (nạp tài liệu tri thức), và bất kỳ màn hình nào cần nạp một hoặc nhiều tệp lên server.
Khi nào không dùng
Tránh dùng
| Không dùng cho | Dùng thay |
|---|---|
| Một ảnh sản phẩm đơn lẻ, nhỏ, đã có luồng riêng | input type="file" trực tiếp như tab Ảnh của catalogue (C7/008) -- không mọi tải tệp đều cần đổi sang FileDrop |
Dựng từ
| Primitive tầng 1 | Vai trong composite |
|---|---|
| EmptyMedia | Hộp chứa icon tài liệu |
| Progress | Thanh tiến độ khi state="uploading" |
Anatomy
| # | Phần | Ghi chú |
|---|---|---|
| 1 | Vùng bấm/kéo-thả | <button type="button"> viền đứt nét, bọc <input type="file" hidden> |
| 2 | Icon | EmptyMedia + FileValidationIcon |
| 3 | Nhãn | children, một dòng |
| 4 | Gợi ý / tiến độ / lỗi | Gợi ý mặc định suy từ maxBytes khi state=idle/dragover; Progress khi uploading; dòng lỗi đỏ dưới ô khi error |
States
| State | Kích hoạt bởi | Hành vi |
|---|---|---|
| idle | Mặc định | Viền border-subtle, đổi border-strong khi hover |
| dragover | Component tự quản (onDragEnter/onDragLeave) | Viền border-strong, nền surface-subtle |
| uploading | Host truyền state="uploading" | Thay gợi ý bằng Progress, aria-busy |
| error | Host truyền state="error" + errorMessage | Viền status-danger-border, dòng lỗi role="alert" dưới ô |
Bàn phím & trợ năng
Seam — host sở hữu gì
FileDrop không gọi server và không enforce maxBytes -- nó chỉ đưa File[] qua onFiles. Host tự tải lên (ví dụ uploadKnowledgeDocument server action), tự quyết định khi nào truyền state="uploading"/"error", và tự đọc lý do lỗi thật từ phản hồi server.
API & triển khai
| Prop | Mặc định | Quy ước |
|---|---|---|
| accept | — | Bắt buộc. Mảng mime hoặc phần mở rộng, truyền thẳng vào input[accept]. |
| maxBytes | — | Bắt buộc. Chỉ dùng để suy gợi ý mặc định -- không lọc tệp. |
| multiple | false | Cho chọn nhiều tệp. |
| disabled | false | Vô hiệu cả bấm lẫn kéo-thả. |
| onFiles | — | Bắt buộc. (files: File[]) => void. |
| state | "idle" | "idle" | "dragover" | "uploading" | "error". dragover thường để component tự set. |
| progress | undefined | 0–100, đọc bởi Progress khi state="uploading". |
| errorMessage | undefined | Hiện khi state="error". |
| hint | suy từ maxBytes | Ghi đè gợi ý mặc định. |
| children | — | Bắt buộc. Nhãn một dòng. |
Design tokens
--nf-component-card-radius, --nf-foundation-space-10 (đệm, hai bậc trên đệm Card), --nf-semantic-border-subtle, --nf-semantic-border-strong, --nf-semantic-surface-raised, --nf-semantic-surface-subtle, --nf-semantic-status-danger-border, --nf-semantic-status-danger-foreground, --nf-semantic-text-primary, --nf-semantic-text-muted.
Do / Don't
Nên dùng
Luôn kèm nhãn rõ định dạng được nhận trong hint hoặc children.
Tránh dùng
Dựa vào FileDrop để chặn tệp quá khổ -- maxBytes không lọc, chỉ gợi ý.