تخطَّ إلى المحتوى

File Upload

منطقة إفلات تعمل بلوحة المفاتيح، وقائمة بالملفات المختارة، مع حالات الإزالة والتقدم والخطأ والتحقق من الملفات.

الإصدار 0.4.1 ·

رفع ملف

التثبيت

bunx --bun shadcn@latest add @dga/file-upload

ويثبّت Field أيضًا.

الاستخدام

page.tsx
tsx
import { Field, FieldLabel } from "@/components/ui/field";
import { FileUpload } from "@/components/ui/file-upload";

export function DocumentsField() {
  return (
    <Field name="documents">
      <FieldLabel>المستندات الداعمة</FieldLabel>
      <FileUpload
        accept=".pdf,.jpg,.png"
        maxSize={5 * 1024 * 1024}
        maxFiles={3}
        hint="PDF أو JPG أو PNG، حتى 5 MB للملف."
        onFilesAdded={(files) => files.forEach(upload)}
      />
    </Field>
  );
}

استخدم File Upload لإرفاق المستندات والصور بطلب. يختار المكوّن الملفات ويفحصها، وأنت ترفعها. مرّر onFilesAdded لبدء الرفع، ثم احتفظ بالقائمة في حالتك (files) وحدّث status وprogress لكل ملف. اذكر الصيغ المقبولة وحد الحجم في hint.

البنية

  • منطقة الإفلات (<label> حول <input> للملفات): المنطقة المنقطة. والحقل هو عنصر التحكم القابل للتركيز.
  • التلميح: الصيغ وحد الحجم.
  • قائمة الملفات (<ul>): صف لكل ملف فيه أيقونة والاسم والحجم أو الحالة وزر إزالة.
  • شريط التقدم (role="progressbar") أثناء رفع الملف.

أمثلة

التحقق

تُفحص الملفات مقابل accept وmaxSize وmaxFiles. ويبقى الملف المرفوض في القائمة مع السبب، فلا يضيع بصمت. جرّب ملفًا أكبر من 5 MB أو ملف .exe. والدالة validateFiles() مصدَّرة إن احتجت الفحص نفسه في مكان آخر.

التحقق

الحالات

تعرض القائمة ملفًا انتهى رفعه وملفًا يُرفع مع التقدم وملفًا مرفوضًا وملفًا ينتظر الرفع. ويمكن تعطيل منطقة الإفلات أو جعلها في حالة خطأ.

الحالات

إظهار التقدم

تحكّم في القائمة عبر files وonFilesChange، وحدّث الملف أثناء رفعه.

page.tsx
tsx
const [files, setFiles] = useState<UploadFile[]>([]);

<FileUpload
  files={files}
  onFilesChange={setFiles}
  onFilesAdded={(added) =>
    added.forEach((file) =>
      upload(file.file, (progress) =>
        setFiles((current) =>
          current.map((f) =>
            f.id === file.id
              ? { ...f, status: progress < 100 ? "uploading" : "done", progress }
              : f,
          ),
        ),
      ),
    )
  }
/>

RTL

يبدأ رمز كل صف ونصه من اليمين، ويقع زر الإزالة على اليسار، ويمتلئ شريط التقدم من اليمين إلى اليسار. وتحتفظ أسماء الملفات باتجاهها (dir="auto" داخل <bdi>): الاسم العربي يُقرأ من اليمين إلى اليسار وreport.pdf من اليسار إلى اليمين. والأحجام والنسب المئوية بأرقام غربية من اليسار إلى اليمين.

LTR (الإنجليزية)
RTL (العربية)

إمكانية الوصول

المفتاحالإجراء
Tabينقل التركيز إلى منطقة الإفلات، ثم عبر أزرار الإزالة.
Space أو Enterيفتح منتقي الملفات.
Enter أو Space على زر الإزالةيزيل ذلك الملف.
  • منطقة الإفلات حقل ملفات أصلي، فهي قابلة للتركيز وتعمل بلوحة المفاتيح وتقنيات المساعدة. والسحب إضافة وليس الطريقة الوحيدة (WCAG 2.1.1).
  • يحيط حد التركيز بالمنطقة كلها. والحد المتقطع بنسبة 3:1 أو أفضل؛ والسحب فوقها يضيف حدًا مصمتًا بلون العلامة وتظليلًا.
  • يحمل كل زر إزالة اسم الملف («إزالة report.pdf»). وتُعلَن حالات الرفض في منطقة حيّة وتظهر في القائمة بأيقونة ونص.
  • لشريط التقدم role="progressbar" مع aria-valuenow؛ وتُكتب النسبة المئوية بجانبه أيضًا.
  • ترجم messages في الصفحات العربية.

مرجع API

FileUpload

منطقة إفلات وقائمة بالملفات المختارة. المنطقة حقل ملف حقيقي، فتعمل بلوحة المفاتيح (Tab ثم Space أو Enter) وبالسحب والإفلات. الملفات التي تفشل في التحقق تبقى في القائمة مع سبب الرفض. سمّها بـ Field.

خصائص FileUpload
الخاصيةالنوعالقيمة الافتراضية
string

اسم الحقل عند إرسال النموذج.

لا توجد قيمة افتراضية
UploadFile[]

الملفات في القائمة (متحكَّم بها). حدّث `status` و`progress` أثناء الرفع.

لا توجد قيمة افتراضية
string

الصيغ المقبولة كما في سمة HTML `accept`: `.pdf,image/*`.

لا توجد قيمة افتراضية
number

أكبر حجم للملف الواحد بالبايت.

لا توجد قيمة افتراضية
number

أكبر عدد من الملفات في القائمة. تكون `multiple` مفعّلة افتراضيًا ما دام العدد أكبر من 1.

لا توجد قيمة افتراضية
UploadFile[]

الملفات التي تبدأ بها القائمة (عند عدم التحكم).

[]
(files: UploadFile[]) => void

تُستدعى بالقائمة كاملة كلما أُضيف ملف أو أُزيل.

لا توجد قيمة افتراضية
(files: UploadFile[]) => void

تُستدعى بالملفات التي اجتازت التحقق، لتبدأ رفعها.

لا توجد قيمة افتراضية
boolean

يتيح عدة ملفات. مفعّل افتراضيًا ما لم تكن `maxFiles` تساوي 1.

لا توجد قيمة افتراضية
string | number | bigint | boolean | ReactElement<unknown, string | JSXElementConstructor<any>> | Iterable<ReactNode> | ReactPortal | Promise<AwaitedReactNode>

يعرض الصيغ المقبولة والحجم تحت منطقة الإفلات.

لا توجد قيمة افتراضية
Partial<FileUploadMessages>

نصوص منطقة الإفلات وحالات الرفع والأخطاء. ترجمها في الصفحات العربية.

لا توجد قيمة افتراضية
boolean

يعطّل منطقة الإفلات.

لا توجد قيمة افتراضية
boolean

لا يمكن إرسال النموذج دون ملف.

لا توجد قيمة افتراضية

يقبل أيضًا جميع خصائص Base UI Field (يفتح في نافذة جديدة).

الاختلافات عن DGA

  • مكوّن واحد لنسختي الملف الواحد والملفات المتعددة في Figma، ومنطقة الإفلات فيه حقل ملفات حقيقي.
  • تبقى الملفات المرفوضة في القائمة مع السبب.
  • تحتفظ أسماء الملفات العربية باتجاهها.
التغييرالسبب
File Upload: drop zoneA drop zone that only accepts a mouse drag is not keyboard accessible (WCAG 2.1.1). Rejected files stay in the list with the reason.
File Upload: Arabic file namesA name mixing Arabic and Latin text must not be reordered around its extension.

عرض جميع الاختلافات (2) لهذا المكوّن أسباب الاختلافات مكتوبة بالإنجليزية.

التباين

70 زوجًا لونيًا فُحص · جميعها تجتاز WCAG 2.1 AAعرض 23 حالة
النمط / الحالةالفاتحالداكن
drop zone border4.57:1 3:13.80:1 3:1
drop zone border, hovered9.73:1 3:112.04:1 3:1
drop zone border, drag over4.54:1 3:17.73:1 3:1
drop zone border, error4.62:1 3:14.65:1 3:1
focus ring17.31:1 3:117.49:1 3:1
hint4.57:1 AA6.32:1 AA
drop zone text18.09:1 AAA15.87:1 AAA
drop zone text, hovered17.31:1 AAA17.04:1 AAA
drop zone text, drag over17.29:1 AAA13.36:1 AAA
drop zone icon4.74:1 3:110.38:1 3:1
drop zone icon, drag over4.53:1 3:18.74:1 3:1
drag over border4.53:1 3:16.50:1 3:1
file name18.09:1 AAA15.87:1 AAA
file size4.77:1 AA6.32:1 AA
error text6.57:1 AA9.01:1 AAA
error icon6.57:1 3:19.01:1 3:1
error border4.83:1 3:14.65:1 3:1
done text5.69:1 AA10.80:1 AAA
done icon5.69:1 3:110.80:1 3:1
progress bar3.83:1 3:18.31:1 3:1
file icon4.77:1 3:19.38:1 3:1
remove button icon18.09:1 3:115.87:1 3:1
remove button icon, hovered16.44:1 3:112.71:1 3:1

يحتاج النص إلى تباين 4.5:1، والأيقونات وحلقات التركيز إلى 3:1. الحالات المعطّلة مستثناة. تقرير التباين الكامل