Skip to content

File Upload

A custom file upload component with drag-and-drop zone, click-to-browse, file list with remove, validation (size/type), and optional preview. Uses Baklava design tokens for consistent styling.

Basic Usage

Use v-model to bind the selected file(s). Single file mode by default.

Single file, any type

vue
<template>
  <BvFileUpload
    v-model="file"
    label="Upload document"
    help-text="Single file, any type"
  />
</template>

<script setup>
import { ref } from "vue";
import { BvFileUpload } from "@baklavue/ui";

const file = ref(null);
</script>

Multiple Files

Set multiple to allow selecting multiple files.

Drag and drop or click to browse

vue
<template>
  <BvFileUpload
    v-model="files"
    multiple
    label="Upload multiple files"
    help-text="Drag and drop or click to browse"
  />
</template>

<script setup>
import { ref } from "vue";
import { BvFileUpload } from "@baklavue/ui";

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

Validation

Use accept, maxSize, minSize, and maxFiles for validation. Listen to the invalid event to display custom error messages.

vue
<template>
  <BvFileUpload
    v-model="files"
    multiple
    accept="image/*"
    :max-size="500 * 1024"
    :max-files="3"
    label="Images only (max 500 KB, 3 files)"
    :invalid-text="invalidText"
    @invalid="handleInvalid"
    @change="handleChange"
  />
</template>

<script setup>
import { ref } from "vue";
import { BvFileUpload } from "@baklavue/ui";
import type { FileUploadInvalidEntry } from "@baklavue/ui";

const files = ref([]);
const invalidText = ref("");
const MAX_SIZE = 500 * 1024; // 500 KB

const handleInvalid = (entries: FileUploadInvalidEntry[]) => {
  const reasons = entries.map((e) => {
    if (e.reason === "type") return `${e.file.name}: invalid type`;
    if (e.reason === "size") return `${e.file.name}: max ${MAX_SIZE / 1024} KB`;
    return `${e.file.name}: max 3 files`;
  });
  invalidText.value = reasons.join(". ");
};

const handleChange = () => {
  invalidText.value = "";
};
</script>

Preview

Enable showPreview to display image thumbnails for uploaded image files.

Accepts images only

vue
<template>
  <BvFileUpload
    v-model="files"
    multiple
    accept="image/*"
    show-preview
    label="Upload images with preview"
    help-text="Accepts images only"
  />
</template>

<script setup>
import { ref } from "vue";
import { BvFileUpload } from "@baklavue/ui";

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

Disabled

Use the disabled prop to prevent user interaction.

Upload is disabled

vue
<template>
  <BvFileUpload
    v-model="file"
    label="Disabled"
    disabled
    help-text="Upload is disabled"
  />
</template>

<script setup>
import { ref } from "vue";
import { BvFileUpload } from "@baklavue/ui";

const file = ref(null);
</script>

Custom Hint Slot

Use the #hint slot to customize the text displayed in the drop zone.

Drop your file here or click to browse
vue
<template>
  <BvFileUpload v-model="file" label="Upload with custom hint">
    <template #hint>
      Drop your file here or <strong>click to browse</strong>
    </template>
  </BvFileUpload>
</template>

<script setup>
import { ref } from "vue";
import { BvFileUpload } from "@baklavue/ui";

const file = ref(null);
</script>

Props

PropTypeDefaultDescription
modelValueFile | File[] | nullundefinedBound files (v-model)
multiplebooleanfalseAllow multiple files
acceptstringundefinedAccepted MIME types or extensions (e.g. image/*, .pdf)
maxSizenumberundefinedMax file size in bytes
minSizenumberundefinedMin file size in bytes
maxFilesnumberundefinedMax file count when multiple
disabledbooleanfalseDisabled state
labelstringundefinedLabel for the upload area
helpTextstringundefinedHelper text below the area
invalidTextstringundefinedError message when validation fails
showPreviewbooleanfalseShow image previews for image files
size"small" | "medium" | "large""medium"Drop zone size

Events

EventPayloadDescription
update:modelValueFile | File[] | nullEmitted when files change (v-model)
invalidFileUploadInvalidEntry[]Emitted when validation fails
changeFile[]Emitted when files are added/removed

Slots

SlotDescription
hintCustom hint text (like "Drag and drop or browse")

Types

typescript
import type {
  FileUploadProps,
  FileUploadInvalidEntry,
  FileUploadInvalidReason,
} from "@baklavue/ui";

interface FileUploadInvalidEntry {
  file: File;
  reason: "type" | "size" | "count";
}

Usage Notes

  • Drag and drop: The drop zone supports both click-to-browse and drag-and-drop. The accept attribute filters the native file picker; drag-and-drop files are validated in JavaScript.

  • Validation: Client-side validation is for UX only. Always validate file types and sizes on the server.

  • Preview: When showPreview is true, object URLs are created for image files. These are automatically revoked when files are removed or the component unmounts.

  • Accessibility: The drop zone is keyboard-accessible via the hidden file input. Use a proper label for screen readers.