File Upload
Mobile-first file upload with MIME-type and size validation, multi-file selection, error states, and read-only file cards.
import { FileUpload, FileCard, FileCardGroup } from "@plexui/ui/components/FileUpload";Examples
Overview
With files
- government-id-scan.pdf2.1 MB
- passport-photo.png340 KB
- non-citizen-travel-2026-approved-document.pdf1.5 MB
Error state
- government-id-scan.pdf2.1 MB
Please upload at least 2 documents.
Disabled
File Card
Standalone file card component. Wrap with FileCardGroup for the bordered container. Omit onRemove to hide the delete button.
Read-only
project-brief.pdf
2.3 MBWith remove
project-brief.pdf
2.3 MBMultiple files
government-id-scan.pdf
2.1 MBpassport-photo.png
340 KBnon-citizen-travel-2026-approved-document.pdf
1.5 MBRead-only list
government-id-scan.pdf
2.1 MBpassport-photo.png
340 KBnon-citizen-travel-2026-approved-document.pdf
1.5 MBAPI
| Prop | Type | Default | Description |
|---|---|---|---|
variant | "compact" | "area" | "compact" | Visual variant: compact button or larger tappable area |
label | string | — | Button label text |
description | string | — | Helper text below the icon (area variant only) |
accept | string | — | Accepted file types (e.g. ".pdf,.png,image/*") |
multiple | boolean | false | Allow selecting multiple files. Without it, a new pick replaces the current file |
maxFiles | number | — | Maximum number of files. Button disables at limit. |
maxSize | number | — | Maximum file size in bytes |
value | File[] | — | Controlled file list |
onValueChange | (files: File[]) => void | — | Callback when files are added or removed |
onFileReject | (file: File, reason: string) => void | — | Callback when a file is rejected (wrong type, too large, over limit) |
errorMessage | string | — | Error message. Sets the invalid visual state |
invalid | boolean | false | Invalid state (auto-set when errorMessage is provided) |
disabled | boolean | false | Disable all interactions |
id | string | — | Id of the hidden file input |
className | string | — | Additional CSS class |
Files are picked with the button (or the area); dropping files on it is not supported.
FileCard
| Prop | Type | Default | Description |
|---|---|---|---|
file | File | — | The file to display |
onRemove | () => void | — | Remove callback. When omitted, the delete button is hidden. |
disabled | boolean | false | Disable the remove button |
className | string | — | Additional CSS class |
FileCardGroup
| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | — | FileCard elements |
className | string | — | Additional CSS class |
Styling
File Upload reads these component tokens. Override them at any scope to restyle it:
--field-error-margin-top: error margin top (default0.5rem)--file-upload-area-border-radius: area border radius (defaultvar(--radius-xl))--file-upload-area-min-height: area min height (default10rem)--file-upload-gutter: gutter (defaultvar(--floating-input-gutter))--file-upload-list-gap: list gap (default0.5rem)--floating-input-background: background (defaultvar(--color-surface))--floating-input-border-color: border color--floating-input-border-color-hover: border color hover--floating-input-border-color-invalid: border color invalid (defaultvar(--color-border-danger-outline))--floating-input-transition-duration: transition duration (default80ms)--input-text-color: text color (defaultvar(--color-text))