Chuyển tới nội dung

Pro đang mở bán trước. Cài đặt mở từ tháng 1/2027. Xem Pro

Component

FileUpload

Chọn tệp bằng một vùng thả: kéo tệp vào, hoặc nhấp hay nhấn Enter trên nó để mở hộp chọn tệp. Tệp quá lớn hoặc sai loại bị từ chối kèm lý do. Các tệp đã chọn hiện bên dưới với tiến độ tải lên, dấu đã tải lên hoặc lỗi với nút thử lại, và nút gỡ mang tên từng tệp.

  • npm: 2 trực tiếp, 4 tổng
  • registry: 5 trực tiếp, 5 tổng

Xem trước

PNG, JPG hoặc PDF, tối đa 25 MB
  • brief.pdf482 KB
    Đã tải lên
  • site-photo.jpg
  • walkthrough.movThe connection dropped

Props

  • multiple
  • disabled
  • invalid
  • size
  • files
  • limits
import { FileUpload } from "@/components/ui/file-upload"

<FileUpload labels={{ prompt: "Thả tệp vào đây hoặc {browse}", browse: "Chọn tệp", list: "Tệp", remove: "Gỡ {name}", retry: "Thử lại {name}", uploading: "Đang tải lên {name}", done: "Đã tải lên", tooLarge: "Lớn hơn {size}", wrongType: "Loại tệp không được chấp nhận", tooMany: "Bạn có thể thêm tối đa {max} tệp", rejected: "{name}, {error}" }} hint="PNG, JPG hoặc PDF, tối đa 25 MB" defaultValue={sampleUploads} onRetry={retryUpload} />

Cách dùng

Khi nào dùng

  • Cho người dùng thêm tệp vào form, ticket hoặc dự án, bằng cách kéo vào hoặc chọn.
  • Hiện tiến độ tải lên từng tệp, và cho thử lại hoặc gỡ lần tải lên thất bại.

Khi nào không dùng

  • Đính kèm tệp vào tin nhắn chat. Dùng Composer với AttachmentPreview.
  • Hiện tệp đã gửi, dưới dạng liên kết. Dùng AttachmentPreview với href.
  • Chọn một ảnh đại diện cần được xem lớn. Hiện ảnh với một Button đổi.

Biến thể

size

Khoảng đệm, icon và chữ của vùng thả: sm cho bảng bên, lg cho trang chủ yếu là tải lên.

  • PNG, JPG hoặc PDF, tối đa 25 MB
    • brief.pdf482 KB
      Đã tải lên
    • site-photo.jpg
    • walkthrough.movThe connection dropped

    sm

  • PNG, JPG hoặc PDF, tối đa 25 MB
    • brief.pdf482 KB
      Đã tải lên
    • site-photo.jpg
    • walkthrough.movThe connection dropped

    mdmặc định

  • PNG, JPG hoặc PDF, tối đa 25 MB
    • brief.pdf482 KB
      Đã tải lên
    • site-photo.jpg
    • walkthrough.movThe connection dropped

    lg

import { FileUpload } from "@/components/ui/file-upload"

<FileUpload size="sm" labels={{ prompt: "Thả tệp vào đây hoặc {browse}", browse: "Chọn tệp", list: "Tệp", remove: "Gỡ {name}", retry: "Thử lại {name}", uploading: "Đang tải lên {name}", done: "Đã tải lên", tooLarge: "Lớn hơn {size}", wrongType: "Loại tệp không được chấp nhận", tooMany: "Bạn có thể thêm tối đa {max} tệp", rejected: "{name}, {error}" }} hint="PNG, JPG hoặc PDF, tối đa 25 MB" defaultValue={sampleUploads} onRetry={retryUpload} />
<FileUpload labels={{ prompt: "Thả tệp vào đây hoặc {browse}", browse: "Chọn tệp", list: "Tệp", remove: "Gỡ {name}", retry: "Thử lại {name}", uploading: "Đang tải lên {name}", done: "Đã tải lên", tooLarge: "Lớn hơn {size}", wrongType: "Loại tệp không được chấp nhận", tooMany: "Bạn có thể thêm tối đa {max} tệp", rejected: "{name}, {error}" }} hint="PNG, JPG hoặc PDF, tối đa 25 MB" defaultValue={sampleUploads} onRetry={retryUpload} />
<FileUpload size="lg" labels={{ prompt: "Thả tệp vào đây hoặc {browse}", browse: "Chọn tệp", list: "Tệp", remove: "Gỡ {name}", retry: "Thử lại {name}", uploading: "Đang tải lên {name}", done: "Đã tải lên", tooLarge: "Lớn hơn {size}", wrongType: "Loại tệp không được chấp nhận", tooMany: "Bạn có thể thêm tối đa {max} tệp", rejected: "{name}, {error}" }} hint="PNG, JPG hoặc PDF, tối đa 25 MB" defaultValue={sampleUploads} onRetry={retryUpload} />

Ví dụ

Ảnh

accept và maxSize từ chối các tệp khác kèm lý do, và hint nói quy tắc từ trước.

PNG, JPG or GIF, up to 5 MB
import { FileUpload } from "@/components/ui/file-upload"

<FileUpload multiple accept="image/*" maxSize={5000000} hint="PNG, JPG or GIF, up to 5 MB" onFilesAdd={uploadFiles} />

Tiến độ tải lên

Mỗi tệp hiện tiến độ, dấu đã tải lên, hoặc lỗi với nút thử lại.

Up to 25 MB each
  • brief.pdf482 KB
    Uploaded
  • site-photo.jpg
  • walkthrough.movThe connection dropped
import { FileUpload } from "@/components/ui/file-upload"

<FileUpload multiple defaultValue={sampleUploads} onRetry={retryUpload} hint="Up to 25 MB each" />

Có nhãn

Đặt tên trường bằng Label và inputId. maxFiles 1 giữ một tệp.

PDF or Word, up to 10 MB
import { FileUpload } from "@/components/ui/file-upload"
import { Label } from "@/components/ui/label"

<div className="flex w-full flex-col gap-xs">
  <Label htmlFor="resume">Resume</Label>
  <FileUpload inputId="resume" accept=".pdf,.doc,.docx" maxFiles={1} hint="PDF or Word, up to 10 MB" maxSize={10000000} />
</div>

Không hợp lệ

invalid chuyển viền sang danger, và error nói lý do dưới vùng thả.

PDF or image

Add at least one receipt

import { FileUpload } from "@/components/ui/file-upload"

<FileUpload invalid error="Add at least one receipt" hint="PDF or image" accept="application/pdf,image/*" />

Vô hiệu

Uploads open after the review
import { FileUpload } from "@/components/ui/file-upload"

<FileUpload disabled hint="Uploads open after the review" />

Trong bảng bên

size sm giữ vùng thả thấp.

Up to 25 MB each
  • meeting-notes.md6.4 KB
    Uploaded
  • assets.zip12 MB
    Uploaded
import { FileUpload } from "@/components/ui/file-upload"

<FileUpload size="sm" multiple defaultValue={sampleUploadsDone} hint="Up to 25 MB each" />

Nên và không nên

Nên

  • Nói loại tệp được nhận và giới hạn kích thước trong hint, để không ai phải thử sai mới biết.
  • Bắt đầu tải lên trong onFilesAdd và hiện tiến độ từng tệp trong value.
  • Giữ tệp lỗi trong danh sách kèm lý do, và truyền onRetry khi thử lại có thể thành công.

Không nên

  • Đừng giấu input hay thay nó bằng div; input thật cho sẵn hộp chọn tệp, bàn phím và form.
  • Đừng tự gỡ tệp lỗi; để người dùng gỡ.
  • Đừng dùng nó cho một ảnh đại diện hay ảnh bìa cần được xem lớn; hiện ảnh và một nút đổi.

Props

TênKiểuGiá trịMặc địnhMô tả
valueFileUploadItem[]--Các tệp, có kiểm soát. Mỗi mục có id, name, type, size, src, status (uploading, done hoặc error), progress và error.
defaultValueFileUploadItem[]--Các tệp ban đầu, không kiểm soát.
onValueChange(items: FileUploadItem[]) => void--Được gọi với cả danh sách sau khi tệp được thêm hoặc gỡ.
onFilesAdd(items: FileUploadItem[]) => void--Được gọi với các tệp mới được chấp nhận, để bắt đầu tải lên.
onRemove(item: FileUploadItem) => void--Được gọi khi nút gỡ được nhấn, trước khi danh sách đổi, để hủy lần tải lên.
onRetry(item: FileUploadItem) => void--Hiện nút thử lại trên các lần tải lên thất bại và được gọi khi nút được nhấn.
acceptstring--Loại tệp, như trên input, như image/*,.pdf. Tệp thả vào thuộc loại khác bị từ chối.
maxSizenumber--Tệp lớn nhất tính bằng byte. Tệp lớn hơn được liệt kê kèm lỗi.
maxFilesnumber--Số tệp tối đa trong danh sách. Tệp vượt quá không được thêm, và một thông báo nói điều đó.
multipleboolean-falseCho phép nhiều hơn một tệp. Không có nó, tệp mới thế chỗ tệp cũ.
disabledboolean-falseTắt vùng thả và các nút.
invalidboolean-falseĐánh dấu trường không hợp lệ, với viền danger. Dùng kèm error.
errorReact.ReactNode--Lý do trường không hợp lệ, hiện dưới vùng thả và được đọc cùng input.
hintReact.ReactNode--Một dòng dưới lời nhắc, như loại tệp và giới hạn kích thước.
sizeenumsm | md | lgmdKhoảng đệm, icon và chữ của vùng thả: sm cho bảng bên, lg cho trang chủ yếu là tải lên.
namestring--Tên của input, để gửi form.
inputIdstring--id của input, cho Label với htmlFor.
formatSize(bytes: number) => string--Định dạng kích thước tệp và maxSize. Mặc định theo đơn vị thập phân, như 482 KB.
labelsFileUploadLabels--Các chữ: prompt ({browse} đánh dấu chỗ nút), browse, list, remove, retry, uploading ({name}), done, tooLarge ({name}, {size}), wrongType ({name}, {accept}), tooMany ({max}), rejected ({name}, {error}). Tiếng Việt gợi ý: Thả tệp vào đây hoặc {browse}, Chọn tệp, Tệp, Gỡ {name}, Thử lại {name}, Đang tải lên {name}, Đã tải lên, Lớn hơn {size}, Loại tệp không được chấp nhận, Bạn có thể thêm tối đa {max} tệp, {name}, {error}.

Cấu tạo

PhầnMô tả
rootCột: vùng thả, lỗi, rồi danh sách tệp.
dropzoneVùng viền nét đứt nhận tệp thả vào và mở hộp chọn tệp, nền sunken, viền control. Hover thêm lớp phủ hover.
inputinput type=file thật, ẩn đi về mặt hiển thị trong vùng thả.
iconIcon tải lên 16px trong một vòng tròn raised. Vòng tròn cố định 32, 40 hoặc 48px, là hình minh họa, không theo cỡ control.
promptLời nhắc và nút chọn tệp.
browseChọn tệp, vẽ như Button secondary. Là một phần của label, không phải điều khiển thứ hai.
hintLoại tệp và giới hạn, bằng chữ secondary.
errorLý do trường không hợp lệ, hoặc thông báo maxFiles, bằng màu danger.
listDanh sách tệp đã chọn.
itemMột ô tệp bố cục như AttachmentPreview: ảnh thu nhỏ, tên trên kích thước, tiến độ hoặc lỗi, rồi dấu và các nút.
thumbnailẢnh hoặc icon loại tệp.
imageẢnh thu nhỏ của tệp ảnh.
bodyTên ở trên kích thước, thanh tiến độ hoặc lỗi.
nameTên tệp trên một dòng, cắt bằng dấu ba chấm.
metaKích thước tệp.
itemErrorLý do tải lên thất bại hoặc lý do tệp bị từ chối.
doneDấu tích success của tệp đã tải lên.
retryButton icon ghost để thử tải lên lại. Không hiện trên tệp bị từ chối.
removeButton icon ghost để gỡ tệp.

Khả năng truy cập

Role: generic

PhímHành động
TabChuyển tới input tệp trong vùng thả, rồi tới nút thử lại và nút gỡ của từng tệp.
Enter / SpaceTrên vùng thả, mở hộp chọn tệp. Trên nút thử lại hoặc gỡ, thử lại hoặc gỡ tệp đó.
  • Vùng thả chứa một label bao quanh input type=file thật, nên hộp chọn tệp, accept và multiple là của trình duyệt, và trình đọc màn hình đặt tên input bằng lời nhắc và chữ chọn tệp. Hint nằm ngoài label nên chỉ được đọc một lần, như phần mô tả. Enter và Space đều mở hộp chọn tệp.
  • Input được mô tả bằng hint, lỗi và danh sách tệp.
  • invalid đặt aria-invalid trên input; error hiện dưới vùng thả bằng chữ, không chỉ bằng viền đỏ. Thông báo maxFiles được đọc như một alert. Mỗi tệp bị từ chối bởi accept hoặc maxSize được đọc trong một status ẩn, EN `brief.pdf, Larger than 5 MB`.
  • Nút gỡ của mỗi tệp mang tên tệp, EN `Remove brief.pdf`; nút thử lại EN `Retry brief.pdf`. Cả hai được mô tả bằng lỗi của tệp.
  • Tệp đang tải lên có thanh tiến độ tên EN `Uploading brief.pdf`. Tệp đã tải lên có dấu tích với chữ ẩn Uploaded.
  • Sau khi gỡ một tệp, focus trở về input, để không bị mất.

Cài đặt

npx werewolf-ui add file-upload

Chạy npx werewolf-ui init một lần trong app trước khi thêm component. Init cài token, thêm CSS import và luật cho agent. Add cài component này cùng các dependency và giữ nguyên theme của bạn. Xem Cài đặt để biết yêu cầu và cách cài qua registry.