Bỏ qua tới nội dung
Component / 064 / NEXOFRAME

FileDrop

Mẫu chuẩn

Vù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.

Composite tầng 2Dựng từ Empty (EmptyMedia), Progress, Icon4 stateK3a — ADR-KN-001 clause 5

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).

LIVE PREVIEW

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 choDùng thay
Một ảnh sản phẩm đơn lẻ, nhỏ, đã có luồng riênginput 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 1Vai trong composite
EmptyMediaHộp chứa icon tài liệu
ProgressThanh tiến độ khi state="uploading"

Anatomy

#PhầnGhi chú
1Vùng bấm/kéo-thả<button type="button"> viền đứt nét, bọc <input type="file" hidden>
2IconEmptyMedia + FileValidationIcon
3Nhãnchildren, một dòng
4Gợi ý / tiến độ / lỗiGợi ý mặc định suy từ maxBytes khi state=idle/dragover; Progress khi uploading; dòng lỗi đỏ dưới ô khi error

States

StateKích hoạt bởiHành vi
idleMặc địnhViền border-subtle, đổi border-strong khi hover
dragoverComponent tự quản (onDragEnter/onDragLeave)Viền border-strong, nền surface-subtle
uploadingHost truyền state="uploading"Thay gợi ý bằng Progress, aria-busy
errorHost truyền state="error" + errorMessageViền status-danger-border, dòng lỗi role="alert" dưới ô

Bàn phím & trợ năng

Tab tới ô; Enter/Space mở hộp thoại chọn tệp (hành vi gốc của <button>).
aria-describedby trỏ tới gợi ý hoặc thông báo lỗi đang hiển thị.
aria-busy="true" khi state="uploading".

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

PropMặc địnhQuy ướ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.
multiplefalseCho chọn nhiều tệp.
disabledfalseVô 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.
progressundefined0–100, đọc bởi Progress khi state="uploading".
errorMessageundefinedHiện khi state="error".
hintsuy từ maxBytesGhi đè 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 ý.