Vize

File Upload

Accessible, headless file upload with dropzone, native picker, validation, and previews.

Package @vizejs/ui/file-upload
Maturity stable
Own the source vize lib pull file-upload
Requires context, controllable-state, id
Aliases file upload, dropzone, file input, file picker, attachments
Covers HTML input type=file, HTML Drag and Drop API, File and Directory Entries API, Ark UI FileUpload, react-dropzone

Usage

import { FileUpload, FileUploadRoot, FileUploadClear, FileUploadDropzone, FileUploadItem, FileUploadItemDelete, FileUploadItemGroup, FileUploadItemName, FileUploadItemPreview, FileUploadItemSize, FileUploadTrigger } from "@vizejs/ui/file-upload";

Or copy the source into your project with vize lib pull file-upload (see Source Distribution).

API

FileUpload

Source: src/families/form/file-upload/file-upload-root.vue

Props

Prop Type Default Description
id string | null undefined Consumer-owned base id. null and undefined select a deterministic fallback.
modelValue readonly File[] undefined Controlled file list. undefined selects uncontrolled behavior.
defaultValue readonly File[] [] Initial file list for uncontrolled use.
accept string undefined Native accept list: MIME types, type/* wildcards, and .ext suffixes.
multiple boolean false Allow more than one file. Single uploads replace the current file.
maxFiles number Infinity Maximum number of files held at once. Ignored unless multiple is set.
maxSize number undefined Maximum accepted byte size per file.
minSize number undefined Minimum accepted byte size per file.
disabled boolean false Disable picking, dropping, pasting, and removing files.
required boolean false Require at least one file for native form validation.
name string undefined Native input name used for form submission.
form string undefined Id of a form owner outside the root's ancestor chain.
directory boolean false Let the native picker choose whole directories (webkitdirectory).
capture "environment" | "user" undefined Native capture hint for mobile camera and microphone pickers.
validate FileUploadValidator undefined Custom validation run after the built-in type and size checks.
messages FileUploadMessages undefined Replacement factories for built-in rejection messages.
locale string undefined BCP 47 locale used for size formatting. undefined formats with en-US, keeping server and client output identical; pass the app locale (e.g. from useLocale()).
sizeStandard FileUploadSizeStandard "si" Unit convention used by the default size formatter.
formatSize FileUploadSizeFormatter undefined Replacement byte-size formatter.
previewAccept string "image/*" accept-syntax filter for files that receive client-side object-URL previews.

Events

Event Payload Description
update:modelValue [files: readonly File[]] Requested file list for v-model.
change [files: readonly File[], previous: readonly File[]] Fired after any distinct file-list request.
accept [files: readonly File[], source: FileUploadSource] Fired with the files accepted from one pick, drop, paste, or API request.
reject [rejections: readonly FileUploadRejection[], source: FileUploadSource] Fired with the files rejected from one pick, drop, paste, or API request.
invalid [nativeEvent: Event] Fired when native form validation reports the hidden input invalid.

Slots

Slot Slot props Description
default FileUploadSlotState Compound FileUpload parts. Receives the file list, availability, and actions.

Exposed

Member Type Description
addFiles —
clear —
element Readonly<ShallowRef<HTMLElement | null>> Template ref to the rendered root element.
files —
getRelativePath —
id —
inputElement —
openPicker —
removeFile —
reset —
state —

FileUploadRoot

Source: src/families/form/file-upload/file-upload-root.vue

Props

Prop Type Default Description
id string | null undefined Consumer-owned base id. null and undefined select a deterministic fallback.
modelValue readonly File[] undefined Controlled file list. undefined selects uncontrolled behavior.
defaultValue readonly File[] [] Initial file list for uncontrolled use.
accept string undefined Native accept list: MIME types, type/* wildcards, and .ext suffixes.
multiple boolean false Allow more than one file. Single uploads replace the current file.
maxFiles number Infinity Maximum number of files held at once. Ignored unless multiple is set.
maxSize number undefined Maximum accepted byte size per file.
minSize number undefined Minimum accepted byte size per file.
disabled boolean false Disable picking, dropping, pasting, and removing files.
required boolean false Require at least one file for native form validation.
name string undefined Native input name used for form submission.
form string undefined Id of a form owner outside the root's ancestor chain.
directory boolean false Let the native picker choose whole directories (webkitdirectory).
capture "environment" | "user" undefined Native capture hint for mobile camera and microphone pickers.
validate FileUploadValidator undefined Custom validation run after the built-in type and size checks.
messages FileUploadMessages undefined Replacement factories for built-in rejection messages.
locale string undefined BCP 47 locale used for size formatting. undefined formats with en-US, keeping server and client output identical; pass the app locale (e.g. from useLocale()).
sizeStandard FileUploadSizeStandard "si" Unit convention used by the default size formatter.
formatSize FileUploadSizeFormatter undefined Replacement byte-size formatter.
previewAccept string "image/*" accept-syntax filter for files that receive client-side object-URL previews.

Events

Event Payload Description
update:modelValue [files: readonly File[]] Requested file list for v-model.
change [files: readonly File[], previous: readonly File[]] Fired after any distinct file-list request.
accept [files: readonly File[], source: FileUploadSource] Fired with the files accepted from one pick, drop, paste, or API request.
reject [rejections: readonly FileUploadRejection[], source: FileUploadSource] Fired with the files rejected from one pick, drop, paste, or API request.
invalid [nativeEvent: Event] Fired when native form validation reports the hidden input invalid.

Slots

Slot Slot props Description
default FileUploadSlotState Compound FileUpload parts. Receives the file list, availability, and actions.

Exposed

Member Type Description
element HTMLDivElement | null Rendered root element.
inputElement HTMLInputElement | null Hidden native file input used for picking and form submission.
id string Root-owned base id.
files readonly File[] Current file list.
state FileUploadState Stable state token.
openPicker () => void Opens the native file picker unless disabled.
addFiles (files: Iterable<File>) => FileUploadAddResult Validates and adds candidate files as a programmatic (api) request.
removeFile (file: File) => boolean Removes one file and reports whether the list changed.
clear () => boolean Removes every file and reports whether the list changed.
reset () => boolean Restores the default file list and reports whether the list changed.
getRelativePath (file: File) => string | null Relative path recorded for a file dropped inside a directory, or null.

FileUploadClear

Source: src/families/form/file-upload/file-upload-clear.vue

Props

Prop Type Default Description
ariaLabel string undefined Accessible name when the slot has no visible text.

Events

Event Payload Description
click [nativeEvent: MouseEvent] Fired before files are cleared. Call preventDefault() to keep them.

Slots

Slot Slot props Description
default FileUploadActionSlotState Button contents. Receives availability and file count.

Exposed

Member Type Description
count —
disabled —
element Readonly<ShallowRef<HTMLElement | null>> Template ref to the rendered root element.
focus —

FileUploadDropzone

Source: src/families/form/file-upload/file-upload-dropzone.vue

Props

Prop Type Default Description
id string | null undefined Consumer-owned dropzone id. null and undefined derive one from the root id.
openOnClick boolean true Treat the dropzone as a button that opens the native picker on click, Enter, and Space. When false the dropzone is only a drop and paste target without a focus stop.
paste FileUploadPasteScope "self" Where clipboard files are accepted: the focused dropzone, the whole document, or nowhere. document listens while mounted and enabled, and ignores pastes into editable controls (inputs, textareas, contenteditable) outside the dropzone so text pasting keeps working.
rejectDragEffect FileUploadRejectDragEffect "none" dropEffect announced during dragover while the drag preview is rejected. none shows the not-allowed cursor and makes the browser refuse the drop; copy lets the drop happen so it produces typed rejections.
ariaLabel string undefined Accessible name when no visible label or aria-labelledby supplies one.
ariaLabelledby string undefined Space-separated ids that label the dropzone.
ariaDescribedby string undefined Space-separated ids of hints such as accepted types and size limits.

Slots

Slot Slot props Description
default FileUploadDropzoneSlotState Dropzone contents. Receives drag and availability state.

Exposed

Member Type Description
dragging boolean Whether a file drag is over the dropzone.
rejecting boolean Whether the dragged items would be rejected.
disabled boolean Whether interaction is disabled.
state FileUploadDropzoneState Stable state token for styling and tests.
element HTMLDivElement | null Rendered dropzone element.
id string Deterministic dropzone id.
focus (options?: FocusOptions) => void Moves focus to the dropzone.

FileUploadItem

Source: src/families/form/file-upload/file-upload-item.vue

Props

Prop Type Default Description
file (required) File required File described by this item and its parts.

Slots

Slot Slot props Description
default FileUploadItemSlotState Item contents. Receives per-file name, size, type, path, and preview state.

FileUploadItemDelete

Source: src/families/form/file-upload/file-upload-item-delete.vue

Props

Prop Type Default Description
ariaLabel string undefined Accessible name when the slot has no visible text, for example Remove report.pdf.

Events

Event Payload Description
click [nativeEvent: MouseEvent] Fired before the file is removed. Call preventDefault() to keep it.

Slots

Slot Slot props Description
default FileUploadItemSlotState Button contents. Receives per-file state.

FileUploadItemGroup

Source: src/families/form/file-upload/file-upload-item-group.vue

Props

Prop Type Default Description
ariaLabel string undefined Accessible name for the file list.
ariaLabelledby string undefined Space-separated ids that label the file list.

Slots

Slot Slot props Description
default FileUploadItemGroupSlotState List contents, usually one FileUploadItem per entry of items.

FileUploadItemName

Source: src/families/form/file-upload/file-upload-item-name.vue

Slots

Slot Slot props Description
default FileUploadItemSlotState Replaces the file name text. Receives per-file state.

FileUploadItemPreview

Source: src/families/form/file-upload/file-upload-item-preview.vue

Props

Prop Type Default Description
alt string "" Alternative text for the default <img>. Empty marks the preview decorative because FileUploadItemName already names the file.

Slots

Slot Slot props Description
default FileUploadItemPreviewSlotState Replaces the default <img>. Receives the object URL once created on the client.

FileUploadItemSize

Source: src/families/form/file-upload/file-upload-item-size.vue

Slots

Slot Slot props Description
default FileUploadItemSlotState Replaces the formatted size text. Receives per-file state.

FileUploadTrigger

Source: src/families/form/file-upload/file-upload-trigger.vue

Props

Prop Type Default Description
ariaLabel string undefined Accessible name when the slot has no visible text.
ariaDescribedby string undefined Space-separated ids of hints such as accepted types and size limits.

Events

Event Payload Description
click [nativeEvent: MouseEvent] Fired before the picker opens. Call preventDefault() to keep it closed.

Slots

Slot Slot props Description
default FileUploadActionSlotState Trigger contents. Receives availability and file count.

Exposed

Member Type Description
count —
disabled —
element Readonly<ShallowRef<HTMLElement | null>> Template ref to the rendered root element.
focus —

Behavior

Normative state x input -> outcome table for @vizejs/ui/file-upload: file-upload-root.vue, file-upload-dropzone.vue, file-upload-trigger.vue, file-upload-item-group.vue, file-upload-item.vue, file-upload-item-preview.vue, file-upload-item-name.vue, file-upload-item-size.vue, file-upload-item-delete.vue, file-upload-clear.vue, and the pure helpers in file-upload-validation.ts and file-upload-transfer.ts. Every row is proven by the named test.

ID State Input Outcome Evidence
F1 default render root, role="button" dropzone, hidden native <input type="file">, and <ul> expose deterministic ids, name/accept/multiple/required, and data renders dropzone, hidden native input, and list semantics with deterministic ids
F2 enabled trigger click, dropzone click/Enter/Space each activation opens the native picker exactly once; a nested trigger does not also open through the dropzone trigger, click, Enter, and Space open the native picker once each
F3 multiple native picker change validated files append, update:modelValue/change/accept("input") fire with the same File objects, and the native FileList mirrors the value picker changes append validated files, sync the native FileList, and render items
F4 file drag over dropzone nested dragenter/dragleave a depth counter keeps data-dragging until the outermost leave; payloads whose item types fail accept set data-drag-reject and announce dropEffect rejectDragEffect (default none) instead of copy; non-file drags are ignored drag enter and leave track nesting and flag rejected payloads
F5 multiple with limits drop accepted files append up to maxFiles; each rejected file reports every file-invalid-type/file-too-large/too-many-files error via reject("drop") drops add accepted files and emit typed rejections
F6 directory drop drop with webkitGetAsEntry() directories expand depth-first across batched readEntries() calls; nested files expose relativePath, getRelativePath(), and a name title dropped directories expand recursively and keep relative paths
F7 paste="self" / "document" clipboard paste with files files are added with source paste from the dropzone, or from anywhere in the document except editable controls outside the dropzone; the document listener binds after mount and is released while disabled and on unmount paste adds clipboard files on the dropzone or the whole document outside editable controls
F8 single (default) pick or drop one valid file replaces the current file; several files at once are all rejected as too-many-files single uploads replace the current file
F9 previewable files, client mount, remove, unmount object URLs are created lazily after mount only for previewAccept matches and revoked when the file leaves the value or the root unmounts previews create object URLs on the client and revoke them on removal and unmount
F10 files present item delete / clear files are removed and focus moves to the neighbouring delete button, or to the dropzone when the list empties removing and clearing files keeps focus inside the upload
F11 disabled click, drag, drop, paste, delete, API nothing opens or changes; dropzone leaves the tab order with aria-disabled, buttons and the native input are disabled disabled uploads ignore picking, dropping, pasting, and removal
F12 controlled picker change update:modelValue requests the next list while rendered files follow the parent until it accepts controlled value wins until the parent accepts the request
F13 exposed instances addFiles, removeFile, clear, reset, openPicker, focus imperative API validates as source api, reports changes, unwraps reactive props to the consumer's File, and exposes element refs exposes typed state and imperative file controls
F14 required, empty native invalid the event is re-emitted as invalid and focus moves to the dropzone, since the hidden input cannot take focus native invalid events are re-emitted and move focus to the dropzone
F15 locale render sizes sizes use the locale prop, then en-US; sizeStandard="iec" and formatSize replace units formats sizes with the locale prop, IEC units, or a custom formatter
F16 missing provider setup root-bound and item-bound parts fail closed with the shared context diagnostic compound parts require a matching root provider
F17 SSR render twice markup is byte-identical, generated ids are stable, and no object URL or <img> is produced on the server renders byte-identical file upload markup across isolated SSR requests
F18 SSR hydrate server nodes are reused without diagnostics and previews appear only after mount hydrates the file upload without mismatches and creates previews after mount
V1 accept parsing parse comma tokens normalize to any/extension/mime, parameters are dropped, and invalid tokens are ignored like the browser does parses native accept lists into normalized tokens and drops invalid tokens
V2 accept matching match file type/* wildcards, exact MIME essences, and case-insensitive multi-dot extensions match; empty lists accept all matches files by mime wildcard, exact mime, and case-insensitive extension
V3 drag types match type only a type is accept, reject, or unknown when empty or when only extensions could decide decides dragged item types as accept, reject, or unknown
V4 size formatting format bytes SI uses localized Intl units; IEC uses powers of 1024 with KiB suffixes joined by a no-break space; invalid sizes format as zero formats sizes with SI locale units and IEC suffixes
V5 file cap resolve single uploads cap at one; maxFiles floors, clamps at zero, and defaults to unlimited resolves the effective file cap
V6 per-file limits validate type, max size, and min size failures are all reported with default messages reports every per-file failure in check order with default messages
V7 single validate a valid candidate replaces the current file; simultaneous candidates are all too-many-files single uploads replace the current file and reject simultaneous candidates
V8 multiple validate earliest valid candidates fill remaining capacity; overflow is too-many-files multiple uploads append up to maxFiles and reject the overflow
V9 custom validator validate built-in codes reuse default messages, other strings become custom, error objects pass through, and the validator sees files accepted so far custom validators map codes, strings, and error objects
V10 messages validate messages factories and formatSize replace default copy message factories and size formatters replace default copy
T1 transfer inspect types payloads are file drags only when types contains Files recognizes file payloads by the Files drag type
T2 transfer predict rejection rejection is predicted from definite type mismatches and capacity, never from undecidable items predicts drag rejection from item types and capacity only
T3 transfer collect files item files are captured synchronously, with a fallback to files collects plain item files and falls back to the files list
T4 transfer collect directories directory entries are read until an empty batch, depth-first, recording fullPath-relative paths expands dropped directories depth-first across batched readers with relative paths

The hidden native input keeps the value form-associated: after every change its FileList is rebuilt with DataTransfer where the engine allows it, required is only set while the value is empty, and directory maps to webkitdirectory. Preview URLs, focus movement, and document listeners are client-only and are released with the owning effect scope. Consumers must not nest interactive content other than FileUploadTrigger inside a clickable dropzone.