File upload component with drag-and-drop support
Tags: component form upload
FileUpload provides an intuitive interface for uploading files with drag-and-drop support.
Import
<script>
import { FileUpload } from '@classic-homes/theme-svelte';
</script>Basic Usage
<script>
let files = $state([]);
</script>
<FileUpload bind:files />Props
| Prop | Type | Default | Description |
|---|---|---|---|
files |
FileMetadata[] |
[] |
Uploaded files (bindable) |
acceptedTypes |
string[] |
['image/*', 'application/pdf'] |
Accepted MIME types; type/* matches a whole category |
maxSizeBytes |
number |
10485760 (10 MB) |
Max file size in bytes |
maxFiles |
number |
10 |
Max number of files; above 1 the picker allows several at once |
disabled |
boolean |
false |
Disables upload |
error |
string |
- | External error message |
onUpload |
(file: File) => Promise<FileMetadata> |
- | Upload handler; without one, files are kept locally |
onFilesChange |
(files: FileMetadata[]) => void |
- | Called when the file list changes (files added or removed) |
label |
string |
- | Label text |
hint |
string |
- | Hint text shown below the drop zone |
typesLabel |
string |
- | Readable label for the accepted types; derived from acceptedTypes if unset |
previewLayout |
'list' | 'grid' |
'list' |
list rows, or grid media thumbnails |
preview |
boolean |
false |
Open a lightbox when a preview is activated |
id |
string |
generated | Input ID |
class |
string |
- | Additional classes |
Types
interface FileMetadata {
id: string;
filename: string;
contentType: string;
size: number;
url?: string;
progress?: number;
error?: string;
uploading?: boolean;
}Accept Specific Types
Restrict accepted file types by MIME type:
<!-- Images only -->
<FileUpload acceptedTypes={['image/*']} bind:files />
<!-- PDF documents -->
<FileUpload acceptedTypes={['application/pdf']} bind:files />
<!-- Multiple types -->
<FileUpload
acceptedTypes={[
'image/*',
'application/pdf',
'application/msword',
'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
]}
bind:files
/>Multiple Files
maxFiles caps the list; any value above 1 lets the picker select several files at once. Use maxFiles={1} for a single file:
<FileUpload bind:files maxFiles={5} />Size Limits
Set maximum file size:
<FileUpload bind:files maxSizeBytes={5 * 1024 * 1024} error={sizeError} />Custom Upload Handler
Handle file uploads:
<script>
async function handleUpload(file: File): Promise<FileMetadata> {
const formData = new FormData();
formData.append('file', file);
const response = await fetch('/api/upload', {
method: 'POST',
body: formData,
});
const data = await response.json();
return {
id: data.id,
filename: file.name,
contentType: file.type,
size: file.size,
url: data.url,
};
}
</script>
<FileUpload bind:files onUpload={handleUpload} />Examples
Profile Picture
<FileUpload
acceptedTypes={['image/*']}
maxFiles={1}
maxSizeBytes={2 * 1024 * 1024}
bind:files={avatar}
onUpload={uploadAvatar}
/>Document Upload
<FileUpload
acceptedTypes={['application/pdf', 'application/msword']}
maxFiles={10}
maxSizeBytes={10 * 1024 * 1024}
bind:files={documents}
onUpload={uploadDocument}
/>With Progress
Files show upload progress:
<FileUpload
bind:files
onUpload={async (file) => {
// Upload with progress tracking
return await uploadWithProgress(file, (progress) => {
// Progress updates automatically
});
}}
/>Accessibility
- Keyboard accessible drop zone
- Screen reader announcements
- Clear status indicators