Get GliaKit

Forms

File upload

A drag-and-drop zone with click-to-browse, plus file rows that show upload progress, success and retryable errors.

Source
src/components/ui/file-upload.tsx
Figma
FileUpload · state (default, dragover, disabled) · FileItem · status (uploading, complete, error).

Usage

Included in the GliaKit boilerplate. Import it where you need it:

tsx
import { FileUpload, FileItem, formatBytes } from "@/components/ui/file-upload";

When to use

  • Attaching documents or images to a record, like invoices, avatars or imports.
  • Bulk uploads where each file needs its own progress and error handling.
  • FileUpload does not upload anything by itself: it hands you File objects. Wire the upload and progress yourself and render FileItem rows for each file.

Examples

File item statuses

Uploading, complete and error. A complete row without onRemove shows a check; onRetry replaces remove on errors.

Single image

Limit the browse dialog to images and take one file. Dropped files are not filtered by accept, so validate them too.

Disabled

Dims the zone, disables the input and ignores drops. Drag a file over the other examples to see the dragover state.

API reference

FileUpload

A <label> wrapping a visually hidden native file input, so the whole zone is clickable. Highlights while a file is dragged over it.

PropTypeDefaultDescription
onFiles(files: File[]) => void-Required. Called with the dropped or browsed files. Only the first file is passed when multiple is false.
acceptstring-Passed to the file input, e.g. "image/*,.pdf". Applies to the browse dialog only; dropped files are not filtered.
multiplebooleantrueAllow selecting several files at once.
disabledboolean-Dims the zone, disables the input and ignores drops.
hintstring"PNG, JPG or PDF up to 10 MB"Helper text under the prompt. Pass an empty string to hide it.
classNamestring-Classes for the drop zone.

FileItem

One file row: an extension badge, the name, then a progress bar, the size or the error. The trailing action depends on status and the handlers you pass.

PropTypeDefaultDescription
namestring-File name. The extension (up to four letters) becomes the badge.
sizenumber-Size in bytes, shown with formatBytes once complete.
status"uploading" | "complete" | "error"-Uploading shows a progress bar, complete shows the size and "Uploaded", error shows a red border and message.
progressnumber00 to 100, shown while uploading.
errorstring"Upload failed"Short error shown on the right when status is error.
onRemove() => void-Shows a remove button. Without it, a complete row shows a green check instead.
onRetry() => void-Shows a retry button on error rows. It takes the place of the remove button.
classNamestring-Classes for the row.

formatBytes

Helper used by FileItem, exported for your own UI.

PropTypeDefaultDescription
bytesnumber-Returns a string such as "512 B", "84 KB" or "2.4 MB".

Accessibility

  • The drop zone is a native file input inside a label, so it is reachable with Tab and opens the file dialog with Enter or Space. A focus ring shows on the zone while the input has keyboard focus.
  • The label text ("Drag files here or browse" and the hint) is the input's accessible name.
  • While uploading, FileItem renders role="progressbar" with aria-valuenow and an aria-label of "Uploading" plus the file name.
  • Remove and retry buttons are labelled with the file name, e.g. "Remove report.pdf".
  • Status changes are not announced automatically; add an aria-live region if people need to hear when uploads finish.

Related