> Leaf UI 0.8.1 · Package: @ifhover/leaf-ui · Source: 435bab23cad7d343653d9b63b049c0b0601eeefb
> Browser documentation: https://ifhover.github.io/leaf-ui/en/components/upload.html

> For AI agents: the complete documentation index is available at https://ifhover.github.io/leaf-ui/en/llms.txt, the full documentation bundle is available at https://ifhover.github.io/leaf-ui/en/llms-full.txt.

# Upload

Choose or drop files and follow upload progress.

## Choose and validate


Choose filesImages, PDF or text · up to 5 files, 5 MB each

basic.tsx

Copy code

```tsx lineNumbers file="../../../src/examples/en/upload/basic.tsx"
import { Space, Upload } from '@ifhover/leaf-ui';

export function UploadBasic() {
  return (
    <Space direction="vertical" align="stretch">
      <Upload
        multiple
        accept="image/*,.pdf,.txt"
        maxCount={5}
        maxSize={5 * 1024 * 1024}
        hint="Images, PDF or text · up to 5 files, 5 MB each"
      />
    </Space>
  );
}
```

Expand code

## Drag, progress and cancellation


This demo simulates progress locally. Use action or customRequest to connect your upload service.

Click or drop files hereImages only · cancellation and retry supported

advanced.tsx

Copy code

```tsx lineNumbers file="../../../src/examples/en/upload/advanced.tsx"
import type { UploadRequest } from '@ifhover/leaf-ui';

import { Space, Text, Upload } from '@ifhover/leaf-ui';

const demoRequest = ({ signal, onProgress }: UploadRequest) =>
  new Promise<void>((resolve, reject) => {
    let percent = 0;
    const cleanup = () => {
      clearInterval(timer);
      signal.removeEventListener('abort', abort);
    };
    const abort = () => {
      cleanup();
      reject(new DOMException('Aborted', 'AbortError'));
    };
    const timer = setInterval(() => {
      percent += 12;
      onProgress(percent);
      if (percent >= 100) {
        cleanup();
        resolve();
      }
    }, 180);
    signal.addEventListener('abort', abort, { once: true });
    if (signal.aborted) abort();
  });

export function UploadDrag() {
  return (
    <Space direction="vertical" align="stretch">
      <Text tone="muted">
        This demo simulates progress locally. Use action or customRequest to connect your upload
        service.
      </Text>
      <Upload
        drag
        multiple
        accept="image/*"
        maxCount={4}
        customRequest={demoRequest}
        hint="Images only · cancellation and retry supported"
      />
    </Space>
  );
}
```

Expand code

## Usage notes

Without action or customRequest, files remain ready for business-managed submission. action uses XMLHttpRequest for progress: POST sends FormData, PUT sends the raw file. A JSON response may provide url and name; customRequest can return the same fields. Validation applies to chooser and drop; uploads can be cancelled, removed and retried. A custom request must observe signal. Removing files or unmounting cancels requests and releases local preview URLs. Server-side validation is still required.

## Types

```ts
import type { UploadProps, UploadFile, UploadChangeInfo, UploadRejection, UploadRequest, UploadResult, FileItem } from '@ifhover/leaf-ui';
```

## Manual upload and picture cards


Choose files

Start uploadCancel uploads

capabilities.tsx

Copy code

```tsx lineNumbers file="../../../src/examples/upload/capabilities.tsx"
import { Button, Space, Upload, type UploadHandle } from '@ifhover/leaf-ui';

import { useRef } from 'react';

export function Capabilities() {
  const upload = useRef<UploadHandle>(null);
  return (
    <Space direction="vertical" align="stretch">
      <Upload
        ref={upload}
        autoUpload={false}
        concurrency={2}
        multiple
        accept="image/*"
        listType="picture-card"
        paste
        customRequest={async (request) => {
          await new Promise<void>((resolve, reject) => {
            const timer = setTimeout(resolve, 700);
            request.signal.addEventListener(
              'abort',
              () => {
                clearTimeout(timer);
                reject(request.signal.reason);
              },
              { once: true },
            );
          });
          return {};
        }}
      />
      <Space>
        <Button onClick={() => upload.current?.upload()}>
          {'Start upload'}
        </Button>
        <Button variant="outline" onClick={() => upload.current?.abort()}>
          {'Cancel uploads'}
        </Button>
      </Space>
    </Space>
  );
}
```

Expand code

## UploadProps API

| Property          | Type                                                                                                           | Default  | Description                                                   |
| ----------------- | -------------------------------------------------------------------------------------------------------------- | -------- | ------------------------------------------------------------- |
| `fileList`        | `readonly `[`UploadFile`](#uploadfile-api)`[]`                                                                 | `[]`     | Controlled / initial file list                                |
| `defaultFileList` | `readonly `[`UploadFile`](#uploadfile-api)`[]`                                                                 | `[]`     | Controlled / initial file list                                |
| `onChange`        | `(files: `[`UploadFile`](#uploadfile-api)`[], info: `[`UploadChangeInfo`](#uploadchangeinfo-api)`) => void`    | —        | File list and status changes                                  |
| `accept`          | `string`                                                                                                       | —        | Accepted MIME types or extensions, e.g. image/\*,.pdf         |
| `multiple`        | `boolean`                                                                                                      | `false`  | Multiple selection / disabled / dropzone                      |
| `disabled`        | `boolean`                                                                                                      | `false`  | Disable interaction.                                          |
| `drag`            | `boolean`                                                                                                      | `false`  | Multiple selection / disabled / dropzone                      |
| `maxCount`        | `number`                                                                                                       | —        | Maximum total file count                                      |
| `maxSize`         | `number`                                                                                                       | —        | Maximum bytes per file                                        |
| `beforeUpload`    | `(file: File) => boolean \| File \| Promise<boolean \| File>`                                                  | —        | Validate before upload; false rejects, File transforms it     |
| `onReject`        | `(rejections: readonly `[`UploadRejection`](#uploadrejection-api)`[]) => void`                                 | —        | Type, size, count or validation rejections                    |
| `action`          | `string \| ((file: File) => string \| Promise<string>)`                                                        | —        | Upload URL; omitted configuration selects files only          |
| `method`          | `'POST' \| 'PUT'`                                                                                              | `'POST'` | POST sends FormData; PUT sends the raw file                   |
| `headers`         | `Readonly<Record<string, string>>`                                                                             | —        | Request headers                                               |
| `data`            | `Readonly<Record<string, string \| Blob>>`                                                                     | —        | Additional POST form data                                     |
| `withCredentials` | `boolean`                                                                                                      | `false`  | Include credentials in cross-origin requests                  |
| `fieldName`       | `string`                                                                                                       | `'file'` | File field name for POST                                      |
| `customRequest`   | `(request: `[`UploadRequest`](#uploadrequest-api)`) => Promise<`[`UploadResult`](#uploadresult-api)` \| void>` | —        | Custom async upload; use signal for cancellation              |
| `onRemove`        | `(file: `[`UploadFile`](#uploadfile-api)`) => boolean \| void \| Promise<boolean> \| Promise<void>`            | —        | Before removal; return false to keep the file                 |
| `showFileList`    | `boolean`                                                                                                      | `true`   | Display the file list                                         |
| `hint`            | `ReactNode`                                                                                                    | —        | Hint / chooser button or dropzone title                       |
| `children`        | `ReactNode`                                                                                                    | —        | Hint / chooser button or dropzone title                       |
| `name`            | `string`                                                                                                       | —        | Field name in native FormData.                                |
| `form`            | `string`                                                                                                       | —        | ID of the associated native form.                             |
| `required`        | `boolean`                                                                                                      | —        | Require a non-empty value; compound controls validate once.   |
| `autoUpload`      | `boolean`                                                                                                      | `true`   | Start after validation; use ref.upload() when false.          |
| `concurrency`     | `number`                                                                                                       | `3`      | Maximum concurrent upload requests.                           |
| `directory`       | `boolean`                                                                                                      | —        | Choose a directory and its files, subject to browser support. |
| `paste`           | `boolean`                                                                                                      | —        | Accept files from the clipboard.                              |
| `listType`        | `'text' \| 'picture' \| 'picture-card'`                                                                        | `'text'` | File list presentation.                                       |

## UploadFile API

Extends [`FileItem`](#fileitem-api) and adds the fields below.

| Property     | Type                                                         | Default  | Description                    |
| ------------ | ------------------------------------------------------------ | -------- | ------------------------------ |
| `uid`        | `string`                                                     | Required | Required. Unique identifier    |
| `url`        | `string`                                                     | —        | Configure url.                 |
| `name`       | `string`                                                     | —        | Field name in native FormData. |
| `size`       | `number`                                                     | —        | Presentation size.             |
| `type`       | `string`                                                     | —        | Configure type.                |
| `status`     | `'ready' \| 'uploading' \| 'done' \| 'error' \| 'cancelled'` | —        | Configure status.              |
| `percent`    | `number`                                                     | —        | Completion percentage.         |
| `error`      | `string`                                                     | —        | Configure error.               |
| `originFile` | `globalThis.File`                                            | —        | Configure origin file.         |
| `response`   | `unknown`                                                    | —        | Server response                |

## UploadChangeInfo API

| Property | Type                                                                  | Default  | Description             |
| -------- | --------------------------------------------------------------------- | -------- | ----------------------- |
| `file`   | [`UploadFile`](#uploadfile-api)                                       | —        | File that changed       |
| `reason` | `'add' \| 'progress' \| 'success' \| 'error' \| 'remove' \| 'cancel'` | Required | Required. Change reason |

## UploadRejection API

| Property  | Type                                          | Default  | Description                         |
| --------- | --------------------------------------------- | -------- | ----------------------------------- |
| `file`    | `File`                                        | Required | Required. Rejected file             |
| `reason`  | `'type' \| 'size' \| 'count' \| 'validation'` | Required | Required. Rejection reason          |
| `message` | `string`                                      | Required | Required. User-readable explanation |

## UploadRequest API

| Property     | Type                        | Default  | Description                                                 |
| ------------ | --------------------------- | -------- | ----------------------------------------------------------- |
| `file`       | `File`                      | Required | Required. File to upload                                    |
| `signal`     | `AbortSignal`               | Required | Required. Cancellation signal, including removal or unmount |
| `onProgress` | `(percent: number) => void` | Required | Required. Report upload progress                            |

## UploadResult API

| Property   | Type      | Default | Description          |
| ---------- | --------- | ------- | -------------------- |
| `url`      | `string`  | —       | Uploaded URL / name  |
| `name`     | `string`  | —       | Uploaded URL / name  |
| `response` | `unknown` | —       | Application response |

## FileItem API

| Property     | Type                                                         | Default | Description                                       |
| ------------ | ------------------------------------------------------------ | ------- | ------------------------------------------------- |
| `uid`        | `string`                                                     | —       | Stable identifier, recommended                    |
| `url`        | `string`                                                     | —       | File URL                                          |
| `name`       | `string`                                                     | —       | Name, inferred from URL if omitted                |
| `size`       | `number`                                                     | —       | Bytes; omitted sizes are not displayed            |
| `type`       | `string`                                                     | —       | MIME type; inferred from the extension if omitted |
| `status`     | `'ready' \| 'uploading' \| 'done' \| 'error' \| 'cancelled'` | —       | Optional upload status                            |
| `percent`    | `number`                                                     | —       | Upload progress from 0 to 100                     |
| `error`      | `string`                                                     | —       | Error description                                 |
| `originFile` | `File`                                                       | —       | Original browser File                             |

## UploadHandle

| Property | Type                     | Default | Description                                              |
| -------- | ------------------------ | ------- | -------------------------------------------------------- |
| `upload` | `(uid?: string) => void` | —       | Required. Start a specified upload or all pending files. |
| `abort`  | `(uid?: string) => void` | —       | Required. Abort a specified upload or all uploads.       |
| `focus`  | `() => void`             | —       | Required. Focus the control.                             |
