FileUpload
Невизуальная обёртка над произвольным триггером — как правило, кнопкой. Клик по триггеру открывает системный диалог выбора файлов. Используйте, когда загрузка — вспомогательное действие в форме или toolbar, и не нужна отдельная зона перетаскивания.
Когда использовать
- Кнопка «Загрузить файлы» рядом с другими полями формы.
- Иконка-загрузка в toolbar.
- Скрытый триггер, когда загрузка инициируется программно через клик на дочерний элемент.
Когда не подходит: если нужна явная зона drag-n-drop — используйте Dropzone или HiddenDropZone.
Анатомия
Upload mode
single — один файл за раз, повторный выбор заменяет предыдущий; multiple — батч-загрузка, файлы накапливаются.
Поле формы
FileUpload проксирует нативные атрибуты <input type="file"> на скрытый input — компонент работает как полноценное поле формы:
name,id,required,capture,form— стандартные атрибуты;idсвязывает input с<label htmlFor>.innerRef— ссылка на нативный input (для интеграции с react-hook-form:refизregister(name)).onChange— нативныйonChangeinput, вызывается до валидации с исходным событием (точка интеграции с form-библиотеками).disabled— деактивирует триггер и input.
Валидация
Ограничения accept (MIME-тип, шаблон image/* или расширение .pdf; строка или массив) и maxSize (байты) разбивают выбранные файлы на две группы:
- принятые уходят в
onFilesUpload(files); - отклонённые — в
onFilesReject(rejections)с причинойmaxSizeилиmime.
Размер проверяется раньше типа: превысивший лимит файл отклоняется с причиной maxSize.
Установка
pnpm add @cloud-ru/ds-dropzone
import { FileUpload } from '@cloud-ru/ds-dropzone'
Примеры использования
Кнопка-триггер
import { Button } from '@cloud-ru/ds-button';
import { FileUpload } from '@cloud-ru/ds-dropzone';
import { useState } from 'react';
export function FileUploadBasic() {
const [files, setFiles] = useState<File[]>([]);
return (
<div style={{ display: 'flex', gap: 12, flexWrap: 'wrap', alignItems: 'center' }}>
<FileUpload onFilesUpload={setFiles}>
<Button type='button' label='Загрузить файлы' />
</FileUpload>
{files.length > 0 && <span>Выбрано: {files.map(f => f.name).join(', ')}</span>}
</div>
);
}Поле формы с валидацией
import { Button } from '@cloud-ru/ds-button';
import { FileRejection, FileUpload } from '@cloud-ru/ds-dropzone';
import { useState } from 'react';
const MAX_SIZE = 5 * 1024 * 1024;
export function FileUploadFormField() {
const [file, setFile] = useState<File | null>(null);
const [error, setError] = useState<string | null>(null);
const handleReject = (rejections: FileRejection[]) => {
const [first] = rejections;
setError(first?.reason === 'maxSize' ? 'Файл больше 5 МБ' : 'Недопустимый тип файла');
};
return (
<div style={{ display: 'flex', gap: 12, flexWrap: 'wrap', alignItems: 'center' }}>
<FileUpload
name='resume'
id='resume'
required
mode='single'
accept={['.pdf', '.doc', '.docx']}
maxSize={MAX_SIZE}
onFilesReject={handleReject}
onFilesUpload={files => {
if (!files.length) return;
setError(null);
setFile(files[0]);
}}
>
<Button type='button' label='Прикрепить резюме' />
</FileUpload>
{file && <span>{file.name}</span>}
{error && <span>{error}</span>}
</div>
);
}Props
Types
FileUploadProps| Prop | Type | Default | Required | Description |
|---|---|---|---|---|
accept | AcceptInput | — | no | Разрешённые типы файлов: MIME-тип (`image/png`), шаблон (`image/*`) или расширение (`.pdf`). Строка (через запятую, как нативный `accept`) или массив. Задаёт нативный `accept` и валидацию. |
children | ReactElement<any, string | JSXElementConstructor<any>> | — | yes | Триггер открытия диалога выбора файлов (кнопка / лейбл). Клонируется, к нему добавляется `onClick`. |
data-test-id | string | — | no | |
disabled | boolean | false | no | Деактивирует триггер и input. |
innerRef | Ref<HTMLInputElement> | — | no | Ссылка на нативный `<input type="file">` — для интеграции с формами (react-hook-form `ref`). |
maxSize | number | — | no | Максимальный размер одного файла в байтах. Превысившие уходят в `onFilesReject`. |
mode | "multiple" | "single" | multiple | no | Режим выбора файлов |
onChange | ChangeEventHandler<HTMLInputElement> | — | no | Нативный `onChange` скрытого input. Вызывается до валидации с исходным событием — точка интеграции с react-hook-form и другими form-библиотеками. |
onFilesReject | ((rejections: FileRejection[]) => void) | — | no | Колбек с отклонёнными файлами и причиной отказа (`maxSize` / `mime`). Вызывается только когда задан `maxSize` и/или `accept` и есть отклонённые файлы. |
onFilesUpload | (files: File[]) => void | — | yes | Колбек с принятыми файлами (прошедшими проверку `maxSize` и `accept`). |