Basic Dropzone
A dashed drop area with a real file input that stays reachable by keyboard and screen reader.
3 frameworksBeginner
A tabbed control offering a file picker on one tab and a validated URL field on the other.
<!--
Resting state (file tab active). The tab switch and the added-sources list are
stateful, so they live in the React/TS tabs - with real role="tab"/tabpanel
wiring. Both routes stay keyboard-reachable: a real file input under a label,
and a real <form> with a labelled URL field.
-->
<div class="w-full max-w-md rounded-xl border border-gray-200 bg-white dark:border-gray-800 dark:bg-gray-900">
<div role="tablist" aria-label="Add a file" class="flex border-b border-gray-200 dark:border-gray-800">
<button type="button" role="tab" aria-selected="true" class="min-h-10 flex-1 border-b-2 border-blue-600 px-3 py-2 text-sm font-semibold text-blue-700 dark:border-blue-400 dark:text-blue-400">Upload file</button>
<button type="button" role="tab" aria-selected="false" class="min-h-10 flex-1 border-b-2 border-transparent px-3 py-2 text-sm font-semibold text-gray-500 hover:text-gray-800 dark:text-gray-400 dark:hover:text-gray-200">From URL</button>
</div>
<div class="p-4">
<input id="split-file-input" type="file" class="peer sr-only" />
<label for="split-file-input" class="flex min-h-10 cursor-pointer items-center justify-center gap-2 rounded-lg border-2 border-dashed border-gray-300 px-4 py-3 text-sm font-semibold text-gray-700 hover:bg-gray-50 peer-focus-visible:ring-2 peer-focus-visible:ring-blue-600 peer-focus-visible:ring-offset-2 peer-focus-visible:ring-offset-white dark:border-gray-700 dark:text-gray-300 dark:hover:bg-gray-800 dark:peer-focus-visible:ring-blue-400 dark:peer-focus-visible:ring-offset-gray-900">
Choose a file from your device
</label>
</div>
</div>| Prop | Type | Default | Description |
|---|---|---|---|
onFile | (file: File) => void | - | On file |
onUrl | (url: string) => void | - | On url |
className | string | - | Additional classes merged onto the root element. |
Two real tabs with `role="tab"`/`tabpanel` wiring share one added-sources list. Both routes stay keyboard-reachable: a file input under a label, and a real `<form>` with a labelled URL field that validates for `http(s)` and reports errors via `aria-invalid`.