Skip to content

Upload ​

File upload with drag-and-drop, progress tracking, image preview, and multiple list styles.

vue
<script setup lang="ts">
import { ref } from 'vue'
import { VxUpload } from 'veloxui'
import type { UploadFile } from 'veloxui'

const files = ref<UploadFile[]>([])
</script>

<template>
  <VxUpload v-model="files" action="/api/upload" />
</template>

Drag and Drop ​

Enable drag for a drop zone area. Users can drag files into the zone or click to browse.

Drop files here or click to browse
Supports JPG, PNG, GIF up to 10MB
vue
<script setup lang="ts">
import { ref } from 'vue'
import type { UploadFile } from 'veloxui'

const files = ref<UploadFile[]>([])
</script>

<template>
  <VxUpload
    v-model="files"
    action="/api/upload"
    drag
    multiple
    tip="Supports JPG, PNG, GIF up to 10MB"
  />
</template>

Picture List ​

Set list-type="picture" to show thumbnails alongside file names.

vue
<script setup lang="ts">
import { ref } from 'vue'
import type { UploadFile } from 'veloxui'

const files = ref<UploadFile[]>([])
</script>

<template>
  <VxUpload
    v-model="files"
    action="/api/upload"
    list-type="picture"
    multiple
    accept="image/*"
  />
</template>

Picture Card ​

Set list-type="picture-card" for a grid of image cards with hover actions (preview and delete).

vue
<script setup lang="ts">
import { ref } from 'vue'
import type { UploadFile } from 'veloxui'

const files = ref<UploadFile[]>([
  { uid: '1', name: 'photo.jpg', status: 'success', url: 'https://picsum.photos/200/200?1' },
  { uid: '2', name: 'avatar.png', status: 'success', url: 'https://picsum.photos/200/200?2' },
])
</script>

<template>
  <VxUpload
    v-model="files"
    action="/api/upload"
    list-type="picture-card"
    multiple
    accept="image/*"
    :limit="6"
  />
</template>

Multiple Files ​

Enable multiple to allow selecting several files at once.

vue
<script setup lang="ts">
import { ref } from 'vue'
import type { UploadFile } from 'veloxui'

const files = ref<UploadFile[]>([])
</script>

<template>
  <VxUpload v-model="files" action="/api/upload" multiple />
</template>

File Limit ​

Set limit to restrict the number of files. The exceed event fires when the user tries to add more.

Maximum 3 files
vue
<script setup lang="ts">
import { ref } from 'vue'
import type { UploadFile } from 'veloxui'

const files = ref<UploadFile[]>([])

function handleExceed(files: File[], limit: number) {
  alert(`You can only upload ${limit} files.`)
}
</script>

<template>
  <VxUpload
    v-model="files"
    action="/api/upload"
    multiple
    :limit="3"
    @exceed="handleExceed"
    tip="Maximum 3 files"
  />
</template>

Max File Size ​

Set max-size (in KB) to reject oversized files. Rejected files show as errors with the size message.

Max 500KB per file
vue
<script setup lang="ts">
import { ref } from 'vue'
import type { UploadFile } from 'veloxui'

const files = ref<UploadFile[]>([])
</script>

<template>
  <VxUpload
    v-model="files"
    action="/api/upload"
    :max-size="500"
    tip="Max 500KB per file"
  />
</template>

Custom Request ​

Use custom-request to handle uploads yourself (e.g. with axios, S3 presigned URLs, etc.).

Using custom upload handler
vue
<script setup lang="ts">
import { ref } from 'vue'
import type { UploadFile, UploadRequestOptions } from 'veloxui'

const files = ref<UploadFile[]>([])

function customUpload(options: UploadRequestOptions) {
  const formData = new FormData()
  formData.append('file', options.file)

  fetch('/api/upload', { method: 'POST', body: formData })
    .then(res => res.json())
    .then(data => options.onSuccess(data))
    .catch(err => options.onError(err.message))
}
</script>

<template>
  <VxUpload
    v-model="files"
    :custom-request="customUpload"
    multiple
  />
</template>

Pre-populated List ​

Pass existing files via v-model to show a pre-populated file list.

report.pdf239.3 KB
data.csv12.1 KB
vue
<script setup lang="ts">
import { ref } from 'vue'
import type { UploadFile } from 'veloxui'

const files = ref<UploadFile[]>([
  { uid: '1', name: 'report.pdf', size: 245000, status: 'success' },
  { uid: '2', name: 'data.csv', size: 12400, status: 'success' },
])
</script>

<template>
  <VxUpload v-model="files" action="/api/upload" />
</template>

Disabled ​

file.pdf120.1 KB
vue
<template>
  <VxUpload v-model="files" disabled />
</template>

Props ​

PropTypeDefaultDescription
modelValueUploadFile[][]File list (v-model)
actionstring''Upload endpoint URL
headersRecord<string, string>—Custom request headers
dataRecord<string, string>—Extra form data fields
namestring'file'Form field name for the file
withCredentialsbooleanfalseSend cookies with request
acceptstring''Accepted file types (e.g. image/*, .pdf)
multiplebooleanfalseAllow multiple file selection
limitnumber0Max number of files (0 = unlimited)
maxSizenumber0Max file size in KB (0 = unlimited)
disabledbooleanfalseDisable upload
dragbooleanfalseEnable drag-and-drop zone
listType'text' | 'picture' | 'picture-card''text'File list display style
showFileListbooleantrueShow file list below trigger
autoUploadbooleantrueUpload immediately on select
customRequest(options: UploadRequestOptions) => void—Custom upload handler
beforeUpload(file: File) => boolean | Promise<boolean>—Hook before upload starts
tipstring''Help text below trigger

Events ​

EventTypeDescription
update:modelValue(files)File list changed
change(file, files)A file was added or its status changed
remove(file, files)A file was removed
success(file, response)Upload succeeded
error(file, error)Upload failed
progress(file, percent)Upload progress updated
exceed(files, limit)File limit exceeded
preview(file)File preview requested (click name or eye icon)

Slots ​

SlotDescription
defaultCustom trigger content (replaces the button or drag zone inner)
tipCustom tip content below the trigger

Exposed Methods ​

MethodDescription
submit()Manually upload all files with status: 'ready' (when autoUpload is false)
trigger()Programmatically open the file picker dialog

UploadFile Interface ​

ts
interface UploadFile {
  uid: string           // Unique identifier
  name: string          // File name
  size?: number         // File size in bytes
  type?: string         // MIME type
  status: 'ready' | 'uploading' | 'success' | 'error'
  percent?: number      // Upload progress (0-100)
  url?: string          // File URL (for pre-existing files)
  thumbUrl?: string     // Thumbnail URL (auto-generated for images)
  raw?: File            // Original File object
  response?: any        // Server response
  error?: string        // Error message
}

UploadRequestOptions Interface ​

ts
interface UploadRequestOptions {
  file: File
  onProgress: (percent: number) => void
  onSuccess: (response: any) => void
  onError: (error: string) => void
}