FileDrop
Drag-and-drop file upload with click-to-browse.
A focusable drop zone that wraps a visually-hidden file input. Drag files in, or activate it with click / Enter / Space to open the native picker. Selections honour `accept` and `multiple`, render each file name with a human-readable size, and expose per-file remove plus a Clear control. Two-way `bind:files` and an `onfiles` callback keep callers in sync; `hint`/`error` provide field chrome and the error is announced to assistive tech.
Demo
Usage
<script>
import { FileDrop } from 'dssoca';
let files = $state([]);
</script>
<FileDrop label="Attachments" bind:files onfiles={(f) => console.log(f)} />
<FileDrop label="Config" accept="application/json,.json" hint="JSON only" />The drop zone is `role="button"` + `tabindex=0` with an `aria-label` derived from the label/hint; the native `<input type="file">` is visually hidden and activated programmatically. WCAG 2.2 AA; vitest-axe clean.
HTML
CSS only — static markup The exact markup the component renders, generated at build time. Use it with dssoca/vanilla.css — see Plain HTML & CSS.
<div class="ss-filedrop">
<span class="lbl" id="file-drop-s1-label">Upload</span>
<input class="native" id="file-drop-s1-input" type="file" accept="image/*" tabindex="-1" aria-hidden="true"/>
<div class="zone" role="button" tabindex="0" aria-label="Upload. PNG or JPG, up to 5 MB" aria-describedby="file-drop-s1-hint">
<span class="prompt">
<span class="title">Drop files here</span>
<span class="sub">or click to browse</span>
</span>
</div>
<span class="msg hint" id="file-drop-s1-hint">PNG or JPG, up to 5 MB</span>
</div>Static zone + hidden input: wire drag/drop and the file list yourself.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
label | string | — | Field label; folded into the zone's accessible name. |
accept | string | — | Native accept filter (e.g. 'application/json,.json'); also enforced on drop. |
multiple | boolean | false | Allow selecting/dropping more than one file. |
disabled | boolean | false | Disables pointer + keyboard activation and mutes the chrome. |
hint | string | — | Supplementary helper text rendered under the zone. |
error | string | — | Error text rendered under the zone; announced to AT via role="alert". |
files | File[] | [] | Selected files. Bindable (`bind:files`). |
onfiles | (files: File[]) => void | — | Fired with the resolved file list whenever the selection changes. |
size | 'sm' | 'md' | 'lg' | — | Per-instance size override; inherits the ancestor `data-size-variant` when unset. |