FileUploader
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
import { FileUploader } from '@nofinite/nui';
<FileUploader onChange={(files) => console.log(files)} />;
With accept filter
<FileUploader accept="image/*" />
Variants
This component does not have visual variants. Styling is handled via CSS and the optional className prop.
Sizes
FileUploader does not provide explicit size variants.
Size can be controlled using CSS (padding, font size, container width).
States
Drag over (active)
Triggered when files are dragged over the dropzone:
- Dashed border changes color
- Background and text color update
- Visual feedback for drop readiness
File list visible
When one or more files are selected:
- A file list is rendered below the dropzone
- Each file shows its name and a remove button
Native Props / Composition
The component internally uses a hidden <input type="file" /> and forwards behavior through the dropzone.
<FileUploader
className="my-custom-uploader"
accept=".pdf,.docx"
multiple
onChange={handleFiles}
/>
You can fully control layout and spacing via className.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
multiple | boolean | false | Allows selecting or dropping multiple files |
accept | string | — | File type filter passed to the native input |
onChange | (files: File[]) => void | — | Callback fired whenever the file list changes |
className | string | "" | Additional class names for custom styling |
placeholder | string | "Drag files here or click to upload" | Text displayed inside the dropzone |
Behavior Notes
- If
multipleisfalse, only the first selected or dropped file is kept. - If
multipleistrue, new files are appended to the existing list. - Removing a file updates internal state and triggers
onChange. - The dropzone is keyboard-accessible and behaves like a button.
<FileUploader multiple onChange={(files) => console.log(files)} />
Accessibility
-
Dropzone renders as a
<div role="button"> -
Keyboard support:
EnterandSpacetrigger file selection
-
Focus-visible outline is shown for keyboard users
-
Remove buttons include
aria-label="Remove file"
Example:
<FileUploader aria-label="Upload documents" />
Layout
- The component is block-level by default
- Stacks vertically: dropzone → file list
- Width is controlled by its container
<div style={{ maxWidth: 400 }}>
<FileUploader />
</div>
Best Practices
Do
- Use
acceptto limit selectable file types - Enable
multipleonly when users genuinely need multi-file uploads - Handle
onChangeto sync files with form or state
Don’t
- Use it without visual spacing in dense layouts
- Rely on it for validation only — always validate files on submit
- Hide the file list if users need confirmation of selected files