File Upload
کامپوننت FileUpload برای انتخاب و مدیریت فایل استفاده میشود؛ مثل آپلود عکس پروفایل یا اسناد. انتخاب فایل با کلیک یا کشیدن و رها کردن (drag & drop) انجام میشود و اعتبارسنجی نوع، حجم و تعداد فایل بهصورت داخلی پشتیبانی میشود.
Import
import { FileUpload } from "fara-ui";
اگر هنوز FaraUI را نصب و راهاندازی نکردهای، ابتدا صفحهی شروع به کار را ببین.
Basic Usage
import { useState } from "react";
import { FileUpload } from "fara-ui";
export function DocumentUpload() {
const [files, setFiles] = useState([]);
return (
<FileUpload
files={files}
accept=".pdf,.docx"
maxSize={5 * 1024 * 1024}
label="فایل مدرک را انتخاب کنید"
hint="PDF یا DOCX، حداکثر ۵ مگابایت"
onFilesSelected={(selected) => setFiles((current) => [...current, ...selected])}
onRemoveFile={(id) => setFiles((current) => current.filter((file) => file.id !== id))}
/>
);
}
کامپوننت state داخلی برای لیست فایلها ندارد؛
filesوonFilesSelected/onRemoveFileرا خودت کنترل کن.
onFilesSelected آبجکتهای UploadedFile را برمیگرداند. فایل اصلی در file قرار دارد و url یک object URL برای preview است:
function handleFilesSelected(selected) {
for (const uploadedFile of selected) {
console.log(uploadedFile.name);
console.log(uploadedFile.file);
console.log(uploadedFile.url);
}
}
Playground
<FileUpload
label="فایل را بکشید و رها کنید یا کلیک کنید"
hint="حداکثر ۲ مگابایت"
onFilesSelected={...}
/>
Validation
سه محدودیت داخلی وجود دارد که فایلهای ردشده را با پیام فارسی زیر dropzone نمایش میدهند:
accept— مثل"image/*"یا".pdf,.docx"؛ فایل با نوع غیرمجاز رد میشود.maxSize— حداکثر حجم هر فایل به بایت.maxFiles— حداکثر تعداد فایل (در حالتmultiple).
برای قوانین سفارشی، validate را پاس بده؛ اگر رشتهای برگرداند، فایل با آن پیام رد میشود. لیست ردشدهها را میتوانی با onRejected دریافت کنی.
<FileUpload
accept="image/*"
maxSize={2 * 1024 * 1024}
maxFiles={3}
validate={(file) => (file.name.includes(" ") ? "نام فایل نباید فاصله داشته باشد" : null)}
onRejected={(rejected) => console.log(rejected)}
onFilesSelected={(selected) => console.log(selected)}
/>
Upload Status
هر آیتم در آرایهی files یک status دارد که حالت آن را در کارت فایل نشان میدهد:
"idle"— هنوز آپلود نشده"uploading"— در حال آپلود؛ اگرprogress(عدد ۰ تا ۱۰۰) بدهی، درصد روی کارت نمایش داده میشود"success"/"error"— آیکون وضعیت؛ در حالت خطا،errorMessageزیر نام فایل نمایش داده میشود
این مقادیر را پس از پیشرفت آپلود واقعی در state خودت بهروز کن.
نمونهی سادهی شبیهسازی آپلود:
async function uploadSelectedFile(selectedFile, setFiles) {
setFiles((current) =>
current.map((file) =>
file.id === selectedFile.id ? { ...file, status: "uploading", progress: 0 } : file,
),
);
try {
await new Promise((resolve) => setTimeout(resolve, 1000));
setFiles((current) =>
current.map((file) =>
file.id === selectedFile.id ? { ...file, status: "success", progress: 100 } : file,
),
);
} catch {
setFiles((current) =>
current.map((file) =>
file.id === selectedFile.id
? { ...file, status: "error", errorMessage: "آپلود ناموفق بود" }
: file,
),
);
}
}
Preview Mode
با variant="preview" کل dropzone به یک پیشنمایش تصویر تبدیل میشود؛ مناسب آپلود تکی عکس مثل عکس پروفایل. تصویر انتخابشده داخل خود dropzone نمایش داده میشود و دکمهی حذف روی آن قرار میگیرد.
Image Preview in a Modal
در حالت پیشفرض، کلیک روی کارت یک عکس، آن را در یک مودال بزرگنمایی میکند (قابل غیرفعالسازی با enablePreviewModal={false}). کلیک روی کارت فایل غیرعکسی، فایل را در تب جدید باز میکند.
Data Attributes and Customize CSS
FileUpload hookهای پایدار مختلفی برای dropzone، خطاها، لیست فایل و وضعیت آپلود دارد:
| Attribute | کاربرد |
|---|---|
data-fara-file-upload | ریشهی کامپوننت |
data-fara-file-upload-dropzone | ناحیهی انتخاب و drag & drop |
data-fara-file-upload-input | input داخلی فایل |
data-fara-file-upload-label | متن اصلی dropzone |
data-fara-file-upload-hint | متن راهنما |
data-fara-file-upload-rejections | فهرست فایلهای ردشده |
data-fara-file-upload-item | کارت هر فایل |
data-fara-file-upload-item-progress | نوار پیشرفت |
data-fara-file-upload-item-remove | دکمهی حذف فایل |
روی dropzone stateهایی مثل data-variant, data-drag-active, data-error و data-disabled قرار میگیرد و روی آیتم فایل data-status قرار دارد:
[data-fara-file-upload-dropzone][data-drag-active] {
border-color: #7c3aed;
background: #f5f3ff;
}
[data-fara-file-upload-item][data-status="uploading"] {
opacity: 0.75;
}
[data-fara-file-upload-item][data-status="error"] {
border-color: #dc2626;
}
برای layout یک نمونهی خاص از className استفاده کن:
<FileUpload className="avatar-upload" onFilesSelected={handleFilesSelected} />
.avatar-upload {
max-width: 420px;
}
Accessibility
- dropzone با
role="button"وtabIndexقابل دسترسی با صفحهکلید است. - وقتی کامپوننت فعال باشد، کلیدهای
EnterوSpaceپنجرهی انتخاب فایل را باز میکنند. - در حالت
disabled، dropzone باaria-disabledعلامتگذاری میشود. - برای توضیح محدودیتها، از
hintاستفاده کن؛ پیام فایلهای ردشده نیز داخل کامپوننت نمایش داده میشود.
SSR Note
FileUpload با SSR و Next.js سازگار است؛ APIهای File، FileList و URL.createObjectURL فقط هنگام تعامل کاربر در مرورگر استفاده میشوند. نیازی به غیرفعالکردن SSR نیست.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
onFilesSelected | (files: UploadedFile[]) => void | - | فایلهای پذیرفتهشده (الزامی) |
files | UploadedFile[] | - | لیست فایلهای فعلی (برای نمایش کارتها) |
onRemoveFile | (id: string) => void | - | با پاسدادن آن، دکمهی حذف نمایش داده میشود |
accept | string | - | محدودیت نوع فایل (مثل "image/*") |
multiple | boolean | false | اجازهی انتخاب چند فایل |
maxSize | number | - | حداکثر حجم هر فایل به بایت |
maxFiles | number | - | حداکثر تعداد فایلها |
validate | (file: File) => string | null | - | قانون اعتبارسنجی سفارشی |
onRejected | (rejected: RejectedFile[]) => void | - | فایلهای ردشده و دلیل آنها |
enablePreviewModal | boolean | true | پیشنمایش عکسها در مودال |
variant | "default" | "preview" | "default" | حالت نمایش |
label | string | «فایل را بکشید و ...» | متن داخل dropzone |
hint | string | - | متن کمکی زیر label |
disabled | boolean | false | غیرفعال کردن dropzone |
className | string | - | کلاس CSS اضافی برای سفارشیسازی |
type FileStatus = "idle" | "uploading" | "success" | "error";
interface UploadedFile {
id: string;
name: string;
url: string;
size?: number;
file?: File;
status?: FileStatus;
progress?: number; // 0-100، در حالت uploading نمایش داده میشود
errorMessage?: string;
}
interface RejectedFile {
name: string;
reason: "type" | "size" | "count";
message: string;
}