The FileDropzone component takes files by drag and drop or by clicking to browse. It checks the type, the size and the number of files, shows what was chosen with image previews, and lets each file be removed again. Underneath it is a real file input, so it submits with the form and works from the keyboard.
Example
Import the component and bind files. Drop a file on the box, or click it to open the file browser.
<script>
import { FileDropzone } from "theui-svelte";
let files = $state<FileList>()
</script>
<FileDropzone bind:files>Attachment</FileDropzone>Multiple Files
Add multiple to accept more than one file, and maxFiles to set a ceiling. New files are added to the ones already chosen, so a second drop does not throw the first away.
<FileDropzone multiple maxFiles={4} text="Drop up to four files" />Type and Size
Use accept exactly as on a file input, with extensions such as .pdf or types such as image/*, and maxSize in bytes. Files that do not pass are handed to onreject, each with the reason: type, size or count.
These checks run in the browser, where anyone can work around them, and the type comes from the file name and what the browser reports. They are there to spare your visitors a pointless upload, not to keep bad files out. Check the type, the size and the number of files again on your server before you store anything.
<FileDropzone
accept=".pdf,.doc,.docx"
maxSize={2 * 1024 * 1024}
hint="PDF or Word, up to 2 MB"
onreject={(rejections) => {
// [{ file, reason: "type" | "size" | "count" }]
console.log(rejections)
}}
>Resume</FileDropzone>Image Previews
Images are shown as thumbnails in the list below the box. Set preview=false to list the names only, or showList=false to hide the list and show the files yourself.
<FileDropzone multiple accept="image/*" text="Drop a few pictures" hint="Images only" />
<!-- Names only -->
<FileDropzone multiple preview={false} />
<!-- No list at all -->
<FileDropzone multiple showList={false} bind:files />Text and Hint
The text prop is the line inside the box and hint is the smaller line under it. Use the hint to say what is allowed, so the rule is known before a file is picked.
<FileDropzone
text="Drag your logo here, or click to browse"
hint="SVG or PNG, at most 500 KB"
accept=".svg,.png"
maxSize={500 * 1024}
/>Custom Content
The content snippet replaces everything inside the box, so you can use your own icon and wording.
<FileDropzone multiple dropzoneClasses="py-10">
{#snippet content()}
<Svg size={2} class="text-brand-500">
<path d="..."/>
</Svg>
<span class="font-semibold">Drop your files</span>
<span class="text-sm text-muted">or click anywhere in this box</span>
{/snippet}
</FileDropzone>Reacting to Files
The onselect callback runs with the files that were accepted, which is the place to start an upload. Everything that was turned away goes to onreject instead.
<FileDropzone
multiple
onselect={(files) => upload(files)}
onreject={(rejections) => showErrors(rejections)}
>Upload</FileDropzone>Disabled
A disabled dropzone takes nothing, by drop or by click, and its list loses the remove buttons.
<FileDropzone disabled text="Uploading is off right now" />Sizes
The size prop sets how tall the drop area is and how large the text inside it reads. It takes "sm", "md", "lg" and "xl", and the default is "md". Inside a Form or a Fieldset the value is inherited.
<FileDropzone size="sm" text="Small" />
<FileDropzone size="md" text="Medium" />
<FileDropzone size="lg" text="Large" />
<FileDropzone size="xl" text="Extra large" />Reset Styles
Set reset to true to drop the dashed border, the hover and the drag highlight and keep only the classes you pass in dropzoneClasses. The drop area keeps its layout and its size, so dropping, clicking and the file list all still work. The default is false, and a Form or a Fieldset can set it for every field it holds.
<FileDropzone
reset
dropzoneClasses="rounded-xl bg-secondary shadow-sm"
text="Drop a file here" />Customization
Use dropzoneClasses for the box, listClasses for the list of chosen files and wrapperClasses for the whole field.
<FileDropzone dropzoneClasses="border-brand-500 bg-brand-500/5" text="Brand coloured" />
<FileDropzone dropzoneClasses="border-solid border-2 py-10" rounded="2xl" text="Solid border" />Accessibility
Drag and drop is never the only way in: the box is a label tied to a real file input, so Tab reaches it, Enter and Space open the file browser, and the same focus ring appears as on any other field. The list of chosen files is a plain list with a named remove button for each file, such as "Remove report.pdf", and each row shows the file size in readable units. Say what is allowed in the hint or helperText, and report what was turned away in your own text through onreject, so the reason is not carried by colour alone.