Skip to content

File Upload

Drag-and-drop file picker with `accept` / `maxSize` / `maxFiles` validation, per-file progress and status, optional folder upload, and an async-cancellable remove hook.

Forms & Inputs·Available inReactVueAngular·View as Markdown

Preview

tsx

Drag & drop a file here, or

Supported formats: PNG, JPG, WEBPMax size: 10.0 MB

Switch the framework picker (top-right of the panel) to render the same demo live in React, Vue, or Angular — same class names, ARIA, and visual output across all three.

Installation

Sisyphos UI ships unified packages for React, Vue, and Angular. Pick the one that matches your stack — every framework exports the same component classes, ARIA semantics, and CSS tokens.

$ pnpm add @sisyphos-ui/react

Then import the bundled stylesheet once at app entry: import "@sisyphos-ui/react/styles.css";

Usage

Idiomatic usage in each supported framework
import { FileUpload } from "@sisyphos-ui/react";

export const Avatar = () => (
  <FileUpload
    label="Profile photo"
    accept="image/*"
    maxSize={2 * 1024 * 1024}
    onChange={(files) => console.log(files)}
  />
);

Max size with onReject

`maxSize` enforces a byte limit; `onReject` receives the rejection reason so you can show a friendly message.

tsx

Drag & drop a file here, or

Max size: 2.0 MB

Error state

Pair `error` with external error messaging for form validation.

tsx

Drag & drop a file here, or

Max size: 10.0 MB

Please attach your CV to continue.

API

PropTypeDefaultDescription
value*UploadedFile[]Controlled list of files, including pre-uploaded items (use `url` instead of `file`).
onChange*(files: UploadedFile[]) => voidCalled with the next file array after add or remove.
labelstringField label rendered above the dropzone.
acceptstringMIME types or extensions accepted by the native input.
maxSizenumber10 * 1024 * 1024Maximum byte size per file.
maxFilesnumber1Maximum file count. With `1`, new uploads replace the existing entry.
multiplebooleanAllow multi-select on the native input. Defaults to `maxFiles > 1`.
directorybooleanfalseAccepts an entire folder via `webkitdirectory`. Each picked file's `webkitRelativePath` is preserved.
supportedFormatsstring[]Human-readable formats shown below the dropzone.
onReject(file: File, reason: RejectReason) => voidCalled when a file fails type / size / count validation.
onBeforeRemove(file: UploadedFile) => boolean | Promise<boolean>Called before a file is removed. Returning `false` cancels the removal — useful for confirmations or revoking server-side resources first.
renderFile(file, handlers) => ReactNodeCustom renderer for each file row.
labelsFileUploadLabelsi18n strings for placeholder, browse button, completed/uploading badges, and remove tooltip.
disabledbooleanfalseDisables the dropzone.
errorbooleanfalseMarks the field as invalid for styling and ARIA.
errorMessagestringMessage shown below the dropzone when `error` is true.

The full API including refs, ARIA attributes, and HTML passthroughs lives in the package README on npm.

Accessibility

  • Native <input type="file"> is hidden but accessible via the surrounding label so screen readers announce the field correctly.
  • Each file row exposes a per-row remove button labeled via labels.remove.
  • Drag state is reflected as a class on the dropzone for users with motion-aware themes.

Keyboard interactions

KeyAction
TabMoves focus to the dropzone, then to each per-file remove button.
EnterthenSpaceActivates the focused control (open browser dialog, remove file).
Need more?View on npm →
Was this page helpful?