Appearance
FileUpload Component
A versatile file upload component supporting single or multiple file uploads with drag-and-drop functionality, file preview integration, and configurable file type restrictions. Displays uploaded files with thumbnails, file information, and management controls.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
modelValue | File | File[] | null | null | The uploaded file(s) - supports v-model binding |
accept | string | "*" | Accepted file types (same format as HTML input accept) |
multiple | boolean | false | Enable multiple file selection |
maxFiles | number | -1 | Maximum number of files allowed (-1 for unlimited) |
dragAndDrop | boolean | true | Enable drag and drop functionality |
columns | number | 2 | Number of columns for file grid (multiple files mode) |
Emits
| Event | Parameters | Description |
|---|---|---|
update:modelValue | File | File[] | null | Emitted when files are added or removed |
Features
Single File Upload
- Clean dropzone with click-to-upload interface
- Shows file preview with thumbnail (for images) or icon (for other files)
- Replace and remove buttons for easy file management
- Displays file name and size information
Multiple File Upload
- Grid layout with configurable columns
- Add more files dynamically (until maxFiles limit)
- Individual remove buttons for each file
- Visual "Add File" tile when more files can be added
Drag and Drop
- Visual feedback during drag operations
- Ring highlight and background change on drag-over
- Handles dropped files automatically
- Can be disabled if not needed
Integrated File Preview
- Click on any file to open the FilePreview component
- Navigation between multiple files in preview mode
- Supports images and PDFs with appropriate viewers
File Type Filtering
- Configurable accept attribute for file type restrictions
- Uses standard HTML input accept format
- Examples:
"image/*",".pdf,.doc","image/png,image/jpeg"
Usage Examples
Basic Single File Upload
vue
<script setup>
import { ref } from "vue";
import { FileUpload } from "dolphin-components";
const file = (ref < File) | (null > null);
const handleSubmit = () => {
if (file.value) {
console.log("Uploading:", file.value.name);
// Submit file to server
}
};
</script>
<template>
<FileUpload v-model="file" accept="image/*" />
<button @click="handleSubmit" :disabled="!file">Upload</button>
</template>Multiple File Upload with Limit
vue
<script setup>
import { ref } from 'vue';
import { FileUpload } from 'dolphin-components';
const files = ref<File[]>([]);
</script>
<template>
<FileUpload
v-model="files"
:multiple="true"
:max-files="5"
accept="image/*,.pdf"
/>
<p class="text-sm text-gray-500">{{ files.length }} / 5 files selected</p>
</template>Custom Grid Layout
vue
<script setup>
import { ref } from 'vue';
import { FileUpload } from 'dolphin-components';
const attachments = ref<File[]>([]);
</script>
<template>
<FileUpload
v-model="attachments"
:multiple="true"
:max-files="9"
:columns="3"
accept=".pdf,.doc,.docx,.xls,.xlsx"
/>
</template>Without Drag and Drop
vue
<script setup>
import { ref } from "vue";
import { FileUpload } from "dolphin-components";
const document = (ref < File) | (null > null);
</script>
<template>
<FileUpload v-model="document" :drag-and-drop="false" accept=".pdf" />
</template>Form Integration
vue
<script setup>
import { ref, computed } from 'vue';
import { FileUpload } from 'dolphin-components';
const formData = ref({
name: '',
email: '',
resume: null as File | null,
documents: [] as File[]
});
const isFormValid = computed(() => {
return formData.value.name &&
formData.value.email &&
formData.value.resume;
});
const submitForm = async () => {
const data = new FormData();
data.append('name', formData.value.name);
data.append('email', formData.value.email);
if (formData.value.resume) {
data.append('resume', formData.value.resume);
}
formData.value.documents.forEach((file, index) => {
data.append(`documents[${index}]`, file);
});
// Submit to server
await fetch('/api/submit', { method: 'POST', body: data });
};
</script>
<template>
<form @submit.prevent="submitForm">
<div class="mb-4">
<label>Name</label>
<input v-model="formData.name" class="input-text" required />
</div>
<div class="mb-4">
<label>Email</label>
<input
v-model="formData.email"
type="email"
class="input-text"
required
/>
</div>
<div class="mb-4">
<label>Resume (Required)</label>
<FileUpload v-model="formData.resume" accept=".pdf,.doc,.docx" />
</div>
<div class="mb-4">
<label>Additional Documents (Optional)</label>
<FileUpload
v-model="formData.documents"
:multiple="true"
:max-files="5"
accept=".pdf,.doc,.docx"
/>
</div>
<button type="submit" class="btn btn-primary" :disabled="!isFormValid">
Submit Application
</button>
</form>
</template>Image Gallery Upload
vue
<script setup>
import { ref } from 'vue';
import { FileUpload } from 'dolphin-components';
const images = ref<File[]>([]);
const uploadToServer = async () => {
for (const image of images.value) {
const formData = new FormData();
formData.append('image', image);
await fetch('/api/gallery/upload', {
method: 'POST',
body: formData
});
}
// Clear after upload
images.value = [];
};
</script>
<template>
<div class="space-y-4">
<h3>Upload Gallery Images</h3>
<FileUpload
v-model="images"
:multiple="true"
:max-files="20"
:columns="4"
accept="image/*"
/>
<div class="flex justify-end gap-2">
<button
@click="images = []"
class="btn btn-outline-secondary"
:disabled="!images.length"
>
Clear All
</button>
<button
@click="uploadToServer"
class="btn btn-primary"
:disabled="!images.length"
>
Upload {{ images.length }} Image(s)
</button>
</div>
</div>
</template>Component States
Empty State (Single File)
- Shows dashed border dropzone
- Cloud upload icon with "Click to upload" text
- Optional "or drag and drop" hint when drag-and-drop is enabled
File Selected State (Single File)
- Shows file card with thumbnail/icon
- Displays file name and formatted size
- Replace button (swap icon) to change file
- Remove button (X icon) to clear selection
Multiple Files State
- Grid of file cards based on
columnsprop - Each card shows thumbnail, name, and size
- Individual remove buttons per file
- "Add File" tile when more files can be added
Drag Over State
- Ring highlight around dropzone
- Light primary color background
- Visual feedback that drop is possible
File Card Features
Thumbnail Display
- Images: Shows actual image thumbnail
- Other Files: Shows document icon
File Information
- Name: Truncated with ellipsis if too long
- Size: Automatically formatted (B, KB, MB, GB)
Size Formatting
| Size Range | Format |
|---|---|
| 0 bytes | "0 B" |
| 1 - 1023 bytes | "X B" |
| 1 KB - 1023 KB | "X.X KB" |
| 1 MB - 1023 MB | "X.X MB" |
| 1 GB+ | "X.X GB" |
Accept Attribute Examples
| Use Case | Accept Value |
|---|---|
| All images | image/* |
| Specific images | image/png,image/jpeg |
| PDF only | .pdf or application/pdf |
| Documents | .pdf,.doc,.docx,.xls,.xlsx |
| Media files | image/*,video/* |
| Any file | * (default) |
TypeScript Support
typescript
import { FileUpload } from "dolphin-components";
// Single file
const singleFile = ref<File | null>(null);
// Multiple files
const multipleFiles = ref<File[]>([]);Props Interface
typescript
interface FileUploadProps {
modelValue: File | File[] | null;
accept?: string;
multiple?: boolean;
maxFiles?: number;
dragAndDrop?: boolean;
columns?: number;
}Best Practices
Usage Recommendations
- Use appropriate
acceptvalues to filter file types early - Set reasonable
maxFileslimits to prevent excessive uploads - Consider file size validation in your submission logic
- Use the integrated preview feature for user experience
Performance Considerations
- Large files are kept in memory - implement server-side chunked upload for very large files
- Image thumbnails are generated via blob URLs
- Consider implementing file size limits server-side as well
Accessibility
- Keyboard accessible file input
- Click anywhere on dropzone to trigger file dialog
- Clear visual states for different interactions
Common Use Cases
- Profile Picture Upload: Single image upload with preview
- Document Attachments: Multiple document upload for forms
- Image Galleries: Bulk image upload with grid preview
- Resume/CV Upload: Single PDF upload with replace functionality
- Product Images: E-commerce product image management
- File Sharing: General-purpose file upload interface