Skip to content

FileUploadField

FileUploadField component for file uploading with drag & drop support, format and size validation, and complete accessibility according to W3C standards.

Usage examples

Basic FileUploadField

Simple upload

vue
<script setup>
import { ref } from 'vue'

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

<template>
  <SuFileUploadField 
    label="Documents"
    placeholder="Select your documents or drag them here"
    message="Accepted formats: PDF, DOC, DOCX"
    v-model="files"
  />
</template>

Multiple upload with validation

Multiple upload with restrictions

vue
<script setup>
const images = ref([])
</script>

<template>
  <SuFileUploadField 
    :multiple="true"
    :maxFiles="3"
    :maxSize="5 * 1024 * 1024"
    accept="image/*"
    label="Images"
    placeholder="Select up to 3 images (max 5MB each)"
    message="Drag and drop your images or click to browse"
    v-model="images"
  />
</template>

Specific file types

File type restrictions

vue
<template>
  <!-- Images only -->
  <SuFileUploadField 
    accept="image/jpeg,image/png,image/gif"
    label="Images only"
    placeholder="JPG, PNG, GIF only"
    message="Accepted formats: JPEG, PNG, GIF"
  />
  
  <!-- Documents -->
  <SuFileUploadField 
    accept=".pdf,.doc,.docx"
    label="Documents"
    placeholder="PDF and Word documents"
    message="Accepted formats: PDF, DOC, DOCX"
  />
  
  <!-- Videos -->
  <SuFileUploadField 
    accept="video/*"
    :maxSize="50 * 1024 * 1024"
    label="Videos"
    placeholder="All video formats (max 50MB)"
    message="All video formats are accepted"
  />
</template>

API

Props

PropTypeDefaultDescription
valueUploadedFile[][]List of uploaded files
multiplebooleanfalseAllow multiple selection
acceptstringundefinedAccepted file types (MIME types or extensions)
maxSizenumber10485760Maximum file size in bytes (10MB default)
maxFilesnumber5Maximum number of files
size'sm' | 'md' | 'lg''md'Component size
state'default' | 'error' | 'success' | 'warning''default'Visual state
disabledbooleanfalseDisable the component
readonlybooleanfalseRead-only mode
requiredbooleanfalseRequired field
labelstringundefinedComponent label
messagestringundefinedDisplayed message
placeholderstring'Select files...'Text displayed in drop zone
dragTextstring'Release to drop...'Text displayed during drag
browseTextstring'Browse'Browse button text
allowPreviewbooleantrueShow image previews
showFileListbooleantrueShow file list

Types

UploadedFile

typescript
interface UploadedFile {
  id: string
  file: File
  name: string
  size: number
  type: string
  status: 'pending' | 'uploading' | 'success' | 'error'
  progress?: number
  error?: string
  preview?: string
}

Events

EventTypeDescription
@update:value(files: UploadedFile[]) => voidEmitted when list changes
@change(files: UploadedFile[]) => voidEmitted on change
@upload(file: UploadedFile) => voidEmitted for each added file
@remove(file: UploadedFile) => voidEmitted when file is removed
@error(error: string, file?: File) => voidEmitted on validation error
@focus(event: FocusEvent) => voidEmitted on focus
@blur(event: FocusEvent) => voidEmitted on blur

File validation

The component performs several automatic validations:

🔍 Validation types

  • File format: Verification against accept prop
  • File size: Verification against maxSize
  • File count: Verification against maxFiles
  • Duplicate files: Prevention of duplicates by name

📝 Accepted formats

vue
<!-- Specific extensions -->
<SuFileUploadField accept=".jpg,.png,.pdf" />

<!-- MIME types -->
<SuFileUploadField accept="image/*,application/pdf" />

<!-- Combination -->
<SuFileUploadField accept="image/*,.pdf,.doc,.docx" />

Accessibility

The FileUpload component follows WCAG 2.1 AA standards:

✅ Accessibility features

  • Keyboard navigation: Complete Tab, Enter, Space support
  • Accessible drag & drop: Drop zone with button role and aria-label
  • ARIA attributes: Labels, descriptions, invalid states
  • Voice announcements: Messages for screen readers with aria-live
  • Visible focus: Clear and contrasted focus indicators
  • Associated labels: Each element has appropriate label
  • State messages: Visual and voice feedback for errors/success
  • Color contrast: WCAG AA compliant ratios
  • Minimum sizes: 44px minimum buttons
  • RTL support: Compatible with right-to-left languages

🎯 Best practices

vue
<!-- Upload with complete validation -->
<SuFileUploadField 
  :multiple="true"
  :maxFiles="5"
  :maxSize="10 * 1024 * 1024"
  accept="image/*,.pdf"
  :required="true"
  label="Supporting documents"
  placeholder="Drag your documents here or click to browse"
  message="Images and PDF accepted, maximum 5 files of 10MB each"
  ariaLabel="Upload zone for supporting documents"
  v-model="documents"
  @error="handleUploadError"
  @upload="handleFileUpload"
/>

<!-- Error handling -->
<script setup>
const handleUploadError = (error, file) => {
  console.error('Upload error:', error, file)
  // Show error notification
}

const handleFileUpload = (file) => {
  console.log('File added:', file)
  // Start upload to server
}
</script>

Keyboard navigation

KeyAction
TabNavigate to/from drop zone
Enter / SpaceOpen file selector
TabNavigate between files in list
Enter / SpaceRemove file (on remove button)

Advanced usage examples

Application form

vue
<script setup>
import { ref } from 'vue'

const cv = ref([])
const coverLetter = ref([])
const portfolio = ref([])

const handleCVUpload = (file) => {
  // Specific processing for CV
  console.log('CV uploaded:', file)
}

const handleError = (error, file) => {
  // Global error handling
  alert(`Error: ${error}`)
}
</script>

<template>
  <form class="application-form">
    <h2>Application</h2>
    
    <SuFileUploadField 
      label="CV (required)"
      accept=".pdf,.doc,.docx"
      :maxSize="5 * 1024 * 1024"
      :maxFiles="1"
      :required="true"
      placeholder="Upload your CV"
      message="PDF or Word format, maximum 5MB"
      v-model="cv"
      @upload="handleCVUpload"
      @error="handleError"
    />
    
    <SuFileUploadField 
      label="Cover letter"
      accept=".pdf,.doc,.docx"
      :maxSize="5 * 1024 * 1024"
      :maxFiles="1"
      placeholder="Upload your cover letter"
      message="PDF or Word format, maximum 5MB"
      v-model="coverLetter"
      @error="handleError"
    />
    
    <SuFileUploadField 
      label="Portfolio (optional)"
      accept="image/*,.pdf"
      :maxSize="20 * 1024 * 1024"
      :maxFiles="10"
      :multiple="true"
      placeholder="Images of your work or PDF"
      message="Images and PDF accepted, maximum 10 files of 20MB each"
      v-model="portfolio"
      @error="handleError"
    />
  </form>
</template>

Publié sous licence MIT.