NUIv3.0.7

File Uploader

A composable, accessible FileUploader component for modern React applications.

tsx
import { FileUploader } from '@nofinite/nui';

Interactive Preview

Loading preview...

FileUploader is a flexible file upload component that supports drag-and-drop, click-to-upload, keyboard interaction, file previews, and file removal. It works for both single and multiple file uploads with optional file type filtering.


Usage

Basic usage

tsx
import { FileUploader } from '@nofinite/nui';

<FileUploader onChange={(files) => console.log(files)} />;

Multiple files

tsx
<FileUploader multiple />

Controlled state

tsx
const [files, setFiles] = useState<File[]>([]);

<FileUploader value={files} onChange={setFiles} />;

With restrictions

tsx
<FileUploader multiple accept="image/*" maxSize={2 * 1024 * 1024} />

Disabled

tsx
<FileUploader disabled />


Subcomponents

None exposed.


Variants

tsx
<FileUploader />
<FileUploader multiple />
<FileUploader disabled />
<FileUploader accept="image/*" />
<FileUploader maxSize={2097152} />

Available variants:

  • single (default)
  • multiple
  • disabled
  • type-restricted
  • size-restricted

Guidelines:

  • Use multiple for gallery or document uploads
  • Always provide accept when backend enforces MIME
  • Use size restriction to avoid unnecessary network cost

Sizes

Layout behavior:

ElementBehavior
Dropzonefull-width container
File listvertical stack
File itemauto height with truncation
Iconsfixed (16–24px)

Sizing is controlled via layout utilities and token spacing.


Shapes / Modes

Interaction states

  • Idle
  • Drag-over
  • File-selected
  • File-removed
  • Disabled

Data modes

  • Controlled
  • Uncontrolled
  • Multi-file aggregation
  • Size-filtered
  • MIME-filtered (native)


Accessibility

Implemented:

  • Dropzone
    • role="button"
    • keyboard activation (Enter/Space)
    • focus-visible outline
    • aria-disabled
    • drag event semantics
  • Remove button
    • aria-label per file
  • Hidden input remains native for browser accessibility
  • Programmatic focus preserved

Limitations:

  • No upload progress semantics
  • No aria-live updates for file list
  • No error announcement for rejected files
  • Drag announcements depend on browser behavior

Animation model

  • File item pop-in via translateY + fade
  • Duration: 200ms
  • Drag-over visual highlight
  • Motion disabled with prefers-reduced-motion

No exit animation for removal.


Architectural notes

Key design decisions:

  • Input proxy pattern
  • Controlled/uncontrolled duality
  • Immutable file list replacement
  • Size validation pre-merge
  • Stable file key generation using name + size + lastModified
  • Drag state isolation
  • Event propagation control

Potential caveat:

  • File object identity used for removal (same file reselect handled via input reset)

Best practices

Do

  • Validate server-side regardless of client filters
  • Provide accept to guide user selection
  • Use multiple for batch uploads
  • Display upload progress externally if needed

Don’t

  • Depend on client MIME filtering for security
  • Upload extremely large files without chunking
  • Store File objects long-term in global state
  • Render heavy previews synchronously

API Reference

PropTypeDefaultDescription
valueFile[]Controlled state for the selected files
defaultValueFile[]Uncontrolled initial state for the selected files
onChange((files: File[]) => void)Callback fired when the list of selected files changes
multiplebooleanfalseWhether to allow multiple files to be selected. Defaults to false.
acceptstringA comma-separated list of allowed file extensions or MIME types (e.g., '.jpg, .png, application/pdf')
maxSizenumberMaximum allowed file size in bytes
classNamestringCustom class name applied to the root container
placeholderReactNodeCustom text or element displayed inside the dropzone (Primary Title)
descriptionReactNodeSecondary text or description below the placeholder
disabledbooleanfalseDisables the dropzone and prevents file selection